L3P |
L3P is a neat little console program that will produce a ready-to-render
POV-file
from any LDRAW
model using any part.
L3P now supports the LGEO library with high quality parts designed
specifically for POV:
POV file generated exclusively from DAT files by the command l3p -b -f -cg30,65 -ca20 -q3 testcar.mpd |
POV file generated from LGEO parts (and a few DAT files) by l3p -b -f -cg30,65 -ca20 -q3 -lgeo testcar.mpd |
Here is one of the models in the 1995 set
4555 Freight Loading Station,
a racing car:
l3p -b -f -ca40 -q3 m4555d.dat |
l3p -b -f -ca40 -q3 -lgeo m4555d.dat |
Here is the 4WD car from the 1995 set
6596 Wave Master.
The POV-Ray
rendering is shown together with the LDraw drawing:
l3p -b -f -q3 m6596a.dat |
ldraw m6596a.dat |
Here is a set from 1970, a veteran car:
l3p -b -f m603 |
ldraw -b7 m603 |
Here you have the model file m603.dat.
You may have a look at the Veteran car in an ad
from a Swedish Disney comic magazine from 1970 scanned by Tore Eriksson.
The car is to the left in the image. You may notice that I have left out
the two clear headlights and added a light on top of the roof in the right
side in stead. This is to check that the image is not mirrored.
From the FAQ, the L-CAD mailing list and various homepages I understood that LDraw was simply drawing lines and 3- and 4-edged polygons. So an obvious idea came to my mind: why not just transfer the polygons to POV? I then studied the format of the DAT-files and the meaning of the line type parameters. I began dissecting the 3004.DAT (Brick 1 x 2) and its subfiles. To ensure that my understanding of the DAT-files was correct and to play with 3D-geometry in general I actually began writing a Win95 program to read the DAT-files and display the lines and polygons in 3D. The main purpose of the display-part of the program was to test the many 3D transformations applied to the polygons, since I wanted to transfer the polygons to POV. The transformations work recursively as you follow the line type 1 inclusion of other DAT-files.
The program had many buttons to experiment with e.g. toggling the different line types on and off. It offered many different views and even let you rotate the model or part by the mouse. I did not, however, put any effort into z-buffering or hidden line/surface removal, as this was not the object of the program, so the display could sometimes be somewhat confusing because lines and polygons were just drawn in the order they appeared in the DAT-files. But it did give a good conception of the 3D geometry.
The program was called L3: when you begin a new project in Microsoft Visual C++ 5.0 you are prompted for a project name, so I just typed L3 for Lego+Ldraw+Lars :-). It was released as L3Lab in February 2000.
I then began generating the POV-files. In stead of drawing the polygons on the display, I simply wrote them to a file in POV syntax. But even for a simple 35 brick model like the 603 Veteran car the number of polygons quickly adds up: 3,400 triangles and 8,300 quads giving a total of 20,000 triangles. No wonder that LDraw may take time (and L3 too :-). So, in my first attempt the POV-file was 23,500 lines long, an overwhelming 1.7 Mega Bytes! It did, however, render relatively fast (<2 minutes for 320x240 no AA, and even <1 minute using meshes (Pentium 100MHz)). Apparently POV is very good at handling triangles.
Well, after some browsing in the POV manual I discovered the matrix
keyword. In stead of feeding POV with all the transformed triangles, why
not let POV take care of the line type 1 transformations? In the next attempt
I made L3 convert each DAT-file into a POV object. The simplest DAT-files
with only line type 3 and 4 became POV object having only triangles. DAT-files
with line type 1 then became POV objects referencing other POV objects
using the matrix for the transformation. The POV-file now got considerably
smaller (950 lines, 49 kBytes) but took slightly longer to render (as POV
now had to do the transformations itself).
The L3 program had all the information about the geometry of the parts in memory, so it knew (or rather was able to calculate) the size and position of the model. With polar coordinates (relative to the center of the bounding box of the model) I only needed to supply the viewing angles and the distance. But how should I define the two angles in an easy understandable way? The answer was right below my feet: the Earth. We all know the globe and the Latitude and the Longitude. Think of a model placed inside a globe, with the center of the model's bounding box placed at the globe's center. You can now easily place camera (and light sources) in the 3D space by specifying Latitude, Longitude and Radius.
The L3 Globe. Click on the globe to see it in 1024x768 (265 kB).
Download the POV source code l3globe.zip (10 kB).
L3 uses LDraw's coordinate system and measures. The floor is parallel
to the XZ-plane and Y is negative upwards. Latitude is in the range from
-90 degrees (south, along the positive y-axis) to 90 degrees (north, along
the negative y-axis). 0 degrees is at the equator.
Longitude is in the range from -180 to 180, where 0 degrees is along
the negative z-axis. 90 degrees (east) is then along the positive x-axis
and -90 degrees (west) is along the negative x-axis.
The basic LDraw views can be represented by these Latitude,Longitude
pairs:
Front=0,0 Right=0,-90 Left=0,90 Back=0,180 Over=90,0 Under=-90,0.
The 3D view can e.g. be 45,45 or 30,45.
But what about the camera distance, the Radius? I really wanted just
to specify the viewing direction (Latitude,Longitude) and then have the
camera to be "as close as possible" in order to minimize the space around
the rendered model. So I devised the following algorithm:
The viewing direction vector will be parallel to the direction given by (Latitude,Longitude) but not necessarily through the globe's center (which is the same as the model's center). To avoid problems with irregular shaped models I used all the bounding boxes of the parts when checking against the pyramid, rather than the total bounding box of the model, which can be "too big". (Ideally all triangles and quads should be considered, but in order to speed up calculation and reduce memory usage the program just fits the bounding boxes of the parts in the model into the camera view, i.e. one level of bounding boxes. (This has, however, turned out to give some problems with irregular shaped sub models, which are just treated as ordinary parts. If it becomes a real nuisance, I might use more levels some day. But often you won't use the closest view anyway, see later)). Some "space" will always exist either horizontally or vertically to maintain the aspect ratio. The calculations turned out somewhat comprehensive and involve solving six equations with six unknowns, but they worked just fine.
The camera position calculation worked well, almost too well: the rendered images might now look a bit distorted (some fish-eye effect), when the camera was moved that close; but remember the object was to minimize the waste of empty rendered area. However, to get a nicer looking image (and a better look at the shadows) it could actually be advantageous to have some "space" a round the model. I obtained this by moving the camera away again from the model along the direction vector. Depending on your taste and the model, you get nice images when moving the camera 5-20% further away (5-20% of the calculated closest radius). After generating the POV-file you can continue experimenting with the camera distance (without generating a new POV-file) simply by editing the line near the end of the file:
#declare PCT = 20 // Percentage further awayand do another rendering. I use POV-Ray for Windows and it has an editing window with the POV-file and buttons for starting/stopping the rendering. You can easily experiment with the POV-file and do some fast, low resolution renderings for previews, before starting the high resolution with anti-aliasing etc.
The positions of the light sources may also be specified as globe coordinates
(polar coordinates), but these are always relative to the center of the
bounding box of the model (and not to the point that the camera is looking
at, as this point may be offset when you choose the closest camera view):
if you want to make an animation I think it would be better to place the
lights relative to the model than to a more or less random camera look-at-position.
However, I ran into a bug in POV-Ray: the disc object did not render correctly. I made a request to comp.graphics.rendering.raytracing and Vahur Krouverk from Estonia was very helpful and examined the POV source code (which is public available) and pointed out the bug ("matrix transformation for disc does not modify disc's normal vector and therefore it gets coloured differently") which was reported to the POV-Ray development team. The error has been fixed in v3.1, but to support older versions L3P can also use a very thin cylinder rather than the disc.
There is one drawback using the primitive substitution. Some complex
parts interface the primitives by drawing triangles and quads up to the
edges of the primitives. When a 16-edged cylinder is then replaced by a
perfectly round cylinder, you get "holes" in the part. E.g. the
6246d
Minifig Tool Box Wrench:
I think that choosing the right colors, textures and light sources is
the most difficult task in rendering. The colors and textures used today
in L3 are empirical values from many experiments. I am not completely satisfied
and would like to hear any suggestions. Currently I use the same RGB color
for normal bricks and for transparent bricks. But this does not seem to
hold for all colors, e.g. color 2 (green) and color 34 (transparent green)
should use two different sets of RGB values. Also it is difficult to determine
the amount of ambient light and the number of light sources. If you use
little ambient light bricks not directly lit become too dark, and if you
use more ambient light especially white bricks tend to get "overexposed".
// Camera (Latitude,Longitude,Radius = 30,45,0)
camera {
#declare PCT = 0; // Percentage further away
#declare STEREO = 0; // Normal view
//#declare STEREO = -degrees(atan2(1,12))/2; // Left view
//#declare STEREO = degrees(atan2(1,12))/2; // Right view
location vaxis_rotate(<117.841,-102.464,-140.713> + PCT/100.0*<119.146,-97.2821,-119.146>,
<-11590.7,-28391.4,11590.7>,STEREO)
sky -y
right -4/3*x
look_at <-1.30431,-5.18241,-21.5678>
angle 67.3801
//orthographic
}
By removing the appropriate comment slashes (//) you may render either
the left or the right image.
A good distance between the eyes is one twelfth of the distance from the eyes to the model (the look_at point). 1/12 corresponds to an angle of 4.8 degrees. You may vary this by replacing 12 with other values (e.g. in the range 5 to 20) in the atan2() function to obtain more or less depth in the scene.
One of the most important new features in v3.1 is that texture is now replaced by material which comprises both interior and texture. Some features like refraction and ior (index of refraction) has been moved from texture to interior, which is really logical: texture is for the surface of an object, interior is for the - yes - interior.
By the use of the #if directive, L3P now generates POV code that runs without any warnings on both v3.0 and 3.1. If you experience a burp from POV, please let me know.
1 4 0 0 0 1 0 0 0 1 0 0 0 1 3001.datto render the part 3001 in red (4).
l3p -c4 3001
As MLCad also supports these colors, L3P does too.
However, Gyugyi packed two RGB's (for dithering) into each Direct Color leaving only 12 bits to each RGB, e.g. 0x04RGBRGB. Some L3P and L3Lab users have asked for the possibility to specify "true colors" (24 bit RGB's), so I have defined the range 0x02000000-0x03FFFFFF for this. 0x02RRGGBB for solid colors and 0x03RRGGBB for transparent.
I will support, but not require, hex notation for colors (0x/0X prefix). You are welcome to specify the color value in decimal ;-)
The following description is partly taken from the LDLite documentation:
3. Direct colors
LDLITE defines the color values from 0x4000000 to 0x7ffffff. These
represent two 12-bit colors which are dithered together, and cannot be
redefined. They are intended to be used in converting meshes from other
3D formats. While you can use decimal numbers, the hex representation makes
the structure clear. The edge color for all direct colors is pure black.
The first (leftmost, most significant) hex digit defines whether the color will be transparent. "4" is an opaque color. "5" or "6" create transparent colors. "7" will create an invisible color which will not be drawn at all. You can interpret the two least significant bits of this digit as inverted alpha values.
The second, third and fourth digits are the red, green and blue intensities of the first dithered color. These digits are ignored for colors in the range 0x6000000 to 0x7ffffff.
The fifth, sixth and seventh digits are the red, green and blue intensities of the second dithered color. For pure colors, set these to the same as the second, third and fourth digits. These digits are ignored for colors in the ranges 0x5000000 to 0x5ffffff and 0x7000000 to 0x7ffffff.
Note that this is the correct description! Paul Gyugyi has swapped the hex ranges in the last two paragraphs in his LDLITE documentation!
I haven't spent any time adjusting the new LDraw colors, they were just
added from the
FAQ.
But I'll play a little with POV again to make some
better colors. Most importantly the transparent colors should not necessarily
be based on the corresponding non-transparent colors, but may have their
own RGB values.
Please make any suggestions.
In the POV file an "#ifndef ColorXX" / "#end" pair is now put around L3P's color definitions. This makes it easier to use your own definitions.
Many parts actually have identical lines. Probably because of copy'n'paste blunders by the author, or because the same line or surface was simply coded twice in the file. Since this is a waste of rendering time, L3P can now report such repeated lines. The DOS version of L3P just reports that a given line has been seen before, the Win32 verson also shows you the line number of the previous occurrence.
Another common mistake is to reference lines with color 16 instead of color 24, so L3P now warns about this. The only legitimate example I have seen is in PARTS\S\973p46a.dat.DAT "~Subpart Minifig Torso with Forestman and Purse Pattern" by Chris Dee where he used color 16 linetype 2 to make sure an outline is visible at low resolution, see also http://news.lugnet.com/cad/dev/?n=4161 and http://news.lugnet.com/cad/dev/?n=4248. A clever but questionable technique because it makes some assumptions about the renderer. All other examples I have seen are errors, and that justifies the "Lines should not use color 16" warning.
Ill-formatted lines like "01 ..." are also noticed.
Bad lines before first valid commands are now allowed. You should now be able to directly render e.g. a DAT or MPD file sent by mail without complaints about the mail header.
L3P -check now checks (recursively) if all subfile references can be found.
Back in August 1999 Lutz Uhlmann agreed that L3P could reference his high quality LGEO POV parts. He promised to send some info regarding the binary format of the element table files. However, I have not heard from him since then, despite several mails.
But since he did consent that L3P could reference the LGEO parts, and since many users have requested it, I've decided to update L3P now anyway. So, with a little hacking I've managed to tweak L3P to use LGEO parts whenever possible. The missing parts are generated on the fly like today.
You now get the best of both worlds: high quality POV parts and L3P's support for automatic camera positioning, primitive substitution, MPD files, TRANSLATE, ROTATE, SCALE, TRANSFORM meta commands, extended colors (direct colors), etc.
Besides the LGEO support several nice features have been added, read on:
Like LDRAW, LGEO also has a set of primitives. Non-LGEO parts
generated on the fly will use some of the LGEO primitives rather than the
L3P primitives (POV equivalents).
Currently the following are used:
stud.dat lg_knob
stud2.dat lg_tech_knob
stud4.dat lg_plate_cylinder
Additionally the L3P studlogo is dynamically added to lg_knob,
so it appears on LGEO parts too when rendering with -q3 (QUAL=3),
see the -q<n> Quality option.
I found out that we (mis)use stud4.dat by scaling its height by 5 in bricks! (and other factors in other parts). LGEO uses lg_plate_cylinder and lg_brick_cylinder and we should use two different studs in LDraw too.
Primitive primitives (grin) like cylinders and discs are OK to be scaled,
but studs should never be scaled - or they cannot be substituted correctly...
The stud4.dat's in
3001.DAT (Brick 2 x 4)
look funny now, because the rounded corner gets scaled by 5...
1) You can download the LGEO parts library
here.
The latest part seems to be from September 23 1999, but there are 842 parts.
Install (extract) the LGEO files to your harddisk in e.g. c:\LDraw\L2P.
There will be a subdirectory named LGEO containing the POV .inc files (include
files) and some table files .tab meant for L2P.
Some LGEO files have bugs so you should also get the latest set of
fixed LGEO parts from
here.
2) L3P needs to know where it can find the three files, L2P_ELMT.TAB,
L2P_COLR.TAB and L2P_PTRN.TAB, which contain info on the LGEO elements,
colors and patterns. The three files are typically located in the directory
named LGEO.
You can tell L3P where the LGEO directory is located either by setting
the environment variable LGEODIR or by adding a line to ldraw.ini.
If LGEODIR is not set, L3P looks for ldraw.ini in C:\Windows (or the
directory specified by the environment variable WINDIR). If found, L3P
uses the LgeoDirectory setting in the [LDraw] section.
L3PAO can handle this for you.
3) You must also tell PovRay where to find the LGEO include files: in POV-Ray for Windows v3.1 select "Edit Settings/Render" in the "Render" menu. Then type +Lc:\LDraw\L2P\LGEO in the "Command line options" box and click the "Set but don't Render" button.
Now you should be all set to take advantage of the high quality LGEO parts.
I've tried to overcome some of the bugs in L2P and in the LGEO parts.
Also transparent LGEO parts are scaled a little bit to avoid
coincident surfaces. The QUAL flag
is supported to substantially speed up test renderings,
see the -q<n> Quality option.
The LGEO colors are darker than L3P's colors.
You can add extra light sources if you want.
See the thread in lugnet.cad.dev Searching for parts.
L3P will print out the number of steps in the model, e.g. 8. You can now
generate the instruction images by:
wine -- L3P.EXE -sc -o car.dat
povray +I car.pov +O car.png +FN +W400 +H300 -J +KFI1 +KFF8 +KI1 +KF8 +D +A
The output images will be named car1.png, car2.png, ..., car8.png.
The StepClock option was added on suggestion from Fredrik Glöckner, who supplied the command lines above. He said: "These are UNIX style command line options. I really have no idea what this looks like in the Windows world. Check the manual."
So, color 24 is now considered illegal for linetypes 1,3 and 4, see the thread in lugnet.cad.dev Colour 24 in non type-2 lines (was Updated S\973S01.DAT).
I had been playing with the idea of embedding POV code in the DAT files
since 1998. It was triggered by the 2473 Brush Car Wash,
which unfortunately uses lines. This is poor design,
it should have used cylinders, which will look correctly if you zoom in.
For rendering the
6649 Street Sweeper
I converted the lines to POV cylinders and it now looked like this (new LGEO
rendering, but still with 2473 generated on the fly):
l3p -b -f -cg22,135 -ca45 -lgeo -q3 m6649.mpd
You can have a look at the POV-friendly 2473 Brush Car Wash in the model file m6649.mpd and in the thread in lugnet.cad.ray Re: Is there some pov-ray friendly version of car wash brush part?.
However, I was reluctant to put it into L3P, because I believed LGEO was the
proper solution to this kind of problem. But after several mails,
Chuck Sommerville made me put into L3P v1.2 - unofficially though.
The POV code embedding can however supplement LGEO and find use in many
cases, so I hereby announce it. I think Chuck Somerville has explained it rather
well in a lugnet.cad.ray posting, so with kind permission from him I'll
quote him on the subject:
From the thread in lugnet.cad.ray
L3P user primitive substitution:
|
Awhile back, I persuaded Lars Hassing to add a feature to L3P. I wanted the
ability to substutite POV language commands in the comments of a .DAT file
that could be used in place of the DAT primitives when rendering through
POV. This would allow users to add native POV commands that could render
better than the triangles and polygons defined in DAT files. Since the
commands are inbedded in comment fields, and only recognized by L3P, they
have no effect of any other tools. Lars was waiting untill I tested the
commands to announce the feature. The good news, is you probably already
have the ability to use these features. He built them into Version 1.2
20000616.
The commands are 0 L3P IFPOV Conditional section begin Begin POV statements in comment statement fields 0 L3P IFNOTPOV Conditional section begin Begin DAT statements 0 L3P ELSEPOV Switch between above section modes 0 L3P ENDPOV Terminate conditional section After running L3P, you can see in the POV file conditionals like if(0) or if(1) To see the alternate version for comparison, just change the constant in these conditionals. If you don't understand any of this, don't worry, I am following this post up with some examples. Remember to get L3P V1.2 or latter to use thse. -Chuck |
L3P still produces the normal object references and meshes in an IFNOTPOV section, but puts a conditional around it.
ldraw -b7 -s0.7 m646 |
l3p -b -f -q3 -ca45 -sw1 -bu m646 |
ldraw -a-1,0,-1,-0.5,1,0.5,1,0,-1 -s0.67 -b1 m6836 |
l3p -cg30,220 -b1 m6836 -sw0 |
ldraw -a1,0,-1,-0.5,1,-0.5,1,0,1 -b1 m6818 |
l3p -cg35,-15 -b1 m6818 -sw0 |
POV-Ray. The Persistence of Vision Raytracer is a high-quality, totally free tool for creating stunning three-dimensional graphics. It is available in official versions for Windows 95/98/NT, DOS, the Macintosh, i86 Linux, SunOS, and Amiga. The source code is available for those wanting to do their own ports.
http://www.povray.org
LGEO PovRay parts by Lutz Uhlmann:
http://www.el-lutzo.de/lego/lgeo.html.
Fixed LGEO parts by Lars C. Hassing:
http://www.hassings.dk/l3/lgeofix.html
LDAO by Steve Bliss:
http://home.earthlink.net/~steve.bliss/ldao/
http://www.ldraw.org/download/win/ldao
LDLite by Paul Gyugyi:
http://www.gyugyi.com/l3g0/ldlite/
http://www.ldraw.org/download/win/ldlite
LdGLite by Don Heyse. Making LDLite portable with OpenGL.
http://ldglite.sourceforge.net
http://www.ldraw.org/download/win/ldglite
MLCad by Michael Lachmann. The Windows CAD program.
http://www.lm-software.com/mlcad/
http://www.ldraw.org/download/win/mlcad
LeoCAD by Leonardo Zide. Windows/Linux CAD program.
http://www.leocad.org
http://www.ldraw.org/download/win/leocad
LDView by Travis Cobbs. Real-time 3D OpenGL viewer.
http://home.san.rr.com/tcobbs/LDView/
http://www.ldraw.org/download/win/ldview
L3Lab by Lars C. Hassing. Viewer/examiner.
http://www.hassings.dk/l3/l3lab.html
http://www.ldraw.org/download/win/l3lab
L3P by Lars C. Hassing
http://www.hassings.dk/l3/l3p.html
Download Area: http://www.hassings.dk/l3/l3p.html#download
http://www.ldraw.org/download/win/l3p
|
LEGO Software Power Tools, Including LDraw, LPub, and Ledit
by Miguel Agullo and
Kevin Clague.
Covering applications such as LDraw, MLCad, LeoCAD, L3P, POV-RAY, BlockCAD, Ldglite, LDAO, and Lpub. Though my name appears on the front page (as a Technical Reviewer) I only reviewed Chapter 8 L3P and POV-Ray. Full credit for the book goes to the two authors Kevin Clague and Miguel Agullo. |
| <a target="_top" href="http://www.hassings.dk/l3/l3p.html"><img border=0 hspace=0 vspace=0 width=88 height=31 src="l3pbanner.gif" alt="To L3P homepage at www.hassings.dk/l3/l3p.html"></a> |
Last updated January 20, 2001