I propose to keep here an up-to-date ldraw.xml, the file used by LDD to convert to and from LDraw files.
Download: latest version
On Windows 32 bits: download and replace the one in “C:\Program Files\LEGO Company\LEGO Digital Designer\”
On Windows 64 bits: download and replace the one in “C:\Program Files (x86)\LEGO Company\LEGO Digital Designer\”
On Mac: download and replace the one in the “Contents\Resources\” folder in the app (open “Applications” in Finder, right click on the “LEGO Digital Designer” package and select the “Show Package Contents” option to explore the pakage folders). (Thanks manglegrat!)
This file is also used and distributed with these tools:
lxf2ldr C++/Qt version (both CLI and GUI), more options but needs to be compiled
lxf2ldr.html HTML/JS version, works everywhere!
If you have other modifications or additions, post them here or send me a personal message and I’ll include them to the benefit of all.
If you need a part, feel free to ask here and I’ll try to add it (provided it exists in LDraw and LDD).
History and Contents
It’s based upon gallaghersart’s latest version (see this thread).
It includes the modifications shutterfreak published in his thread.
It uses some of the LDraw unofficial parts (mainly for new parts in LDD Brick version 2075).
It includes some name corrections (because LDraw renamed or moved some parts, added new variants, etc.).
I tried to more accurately convert the colors (now mainly according to Ryan Howerter’s conversion table). It’s not easy because all sources (Swooshable, Mecabricks, Ryan) don’t agree, and there are holes and overlaps. But as these differences, holes, and overlaps occur for rare colors or colors that aren’t available in LDD, it should be okay.
In a megalomaniacal way, all the entries I have modified have an “SLS” at the end of their heading comments. New entries have an “SLS” at the front of the comments.

So it’s easy to know when to blame me.

As of 2016-09-16 and the big overhaul, I assume all the errors. Know Limitations As of LDD 4.3.9, flex parts (hoses) are not exported anymore (even unflexed). Minifig arms and hands are not connected in LDraw. I don’t know whose geometry is off (both?) but the shapes differ a lot. At least, hands are correctly connected to whatever they clip and arms are correctly placed in their sockets and somewhat wrap around the hands’s stems. Some variants are not recognized by LDD (e.g. clips, or tiles with/without groove, etc.) In those cases, I prefer to use the most recent variant in LDraw as it generally is easier to find and cheaper. Sometimes, several LDD parts correspond to a unique LDraw part. Sometimes, the transformation is accurate for one variant but not for another. For example, the Flag 2 x 2 is known to LDD as 2335, 11055, and 60779, but LDraw only has the 2335 variant. 2335 and 60779 use the same transformation but 11055 is vertically offset. I preferred to badly convert 11055 to 2335 rather than not convert it at all or badly convert 2335 and 60779. ldraw.xml is used both ways (LDD to/from LDraw). It’s not something I do frequently (too many resulting collisions) so it’s not well tested. One problem I can see is that, when several LDD parts correspond to a unique LDraw part, the conversion that’s listed last is the one that will be used. The reverse (first written is the one used) is true for assemblies that use the same subparts, in the same quantity (like electric cables). A lot of LDraw parts are simply wrong. Almost all the parts that combine System (studs and anti-studs) and Technic (pins and axles, and their holes) are wrong in that they assume the technic holes are at the same height than side studs (on the picture below, the circles are concentric).

LDD assumes the holes are 0.2 mm (0.5 LDU) higher.

In ABS, the holes are 0.12 mm (0.375 LDU) higher (dixit Jamie Berard in his famous presentation). In order to limit the number and magnitude of errors, LDD is considered to be right. How to write a new transformation for a part in ldraw.xml What? ldraw.xml is an XML file that defines how LDD can export to (or import from) LDraw files. It does so by defining a match between the part’s IDs and how to rotate and translate the part from one geometry to the other. Matches are defined by “Brick” XML elements. For example, this one says to LDD that the Brick 1x1 that it knows as 3005 is also known to LDraw as 3005: <Brick ldraw="3005.dat" lego="3005" /> (Note the “.dat” in the ldraw ID.) Matches are not needed if the part IDs are the same: the transformation element is sufficient for LDD to know the part exists. (So the example above is useless ) Rotations and translations are defined by “Transformation” XML elements. This one says to LDD that the Brick 1x1 just needs to be moved up: <Transformation ldraw="3005.dat" tx="0" ty="-.96" tz="0" ax="1" ay="0" az="0" angle="0" /> The translation (tx, ty, and tz) is in centimeters (0.8 cm is the width of a brick, 0.96 cm its height). The rotation is given by its axis (the line passing through and ), and its angle in radians. And all the coordinates are in the direct (“riht-handed”), Y points up, coordinates system of LDD. The transformation explains what should be done to import from LDraw besides changing the axes (LDD’s Y is up and XYZ is a direct basis, LDraw’s Y is down and XYZ is an indirect basis; so changing the axes only means changing the sign of Y). So, in an LDD to LDraw point of view, the transformation is reversed: it says what happens to a part if you don’t do anything to its coordinates besides changing the sign of Y. In other words, the opposite transformation has to be applied to the LDD coordinates of the part in order to get the LDraw coordinates (with Y reversed). Why? Each part has an orientation (which way up? which way left?) and a center, point of origin, or reference point (we’ll use “reference point” from now on). But LDD and LDraw don’t always agree. To know the orientation and reference point in LDD, insert the part without rotating it nor attaching it to any other part. It will be aligned along the scene’s axes (LDD’s axes). The reference point is near the mouse pointer’s head. To know the orientation and reference point in LDraw, I find LeoCAD the easiest tool: just select the part and its axes are drawn (X red, Y green, Z blue), starting at its reference point. Okay, LeoCAD’s «X, Y, Z» is LDraw’s «X, -Z, Y» but what’s another little change of basis? Sometimes, their disagreement is trivial. For example, for the simple 1x1 brick (3005), both LDD and LDraw agree: the stud is on top and the reference point is on the vertical line going through the center of the stud. But they differ for the height at which the reference point should be: LDD says it’s at the base of the brick, LDraw at its top (but at the base of the stud). (On every picture, X will be red, Y green, and Z blue.) So the transformation for that part is straightforward: if the LDraw part is imported as is, with only Y reversed, it will end up 0.96 cm (the height of the brick) higher than it should. So we have to lower it by 0.96 cm: <Transformation ldraw="3005.dat" tx="0" ty="-.96" tz="0" ax="1" ay="0" az="0" angle="0" /> Sometimes, their disagreement is more profound and the transformation is therefore more complicated. For example, for the musket (Minifig Gun Musket 2561), LDD puts the reference point in the handle and “up” means the handle is vertical but LDraw puts the reference point in the barrel and “up” means the barrel is vertical. Even more, the stock is on the wrong side, so X and Z are different too. With an identity transformation, the part is rotated by an eighth of a turn (X to Y) (π/4) around the Z axis to put the barrel vertical, and then by a quarter turn (X to Z) (-π/2) around the Y axis. After that, it has been translated up and horizontally. After calculations (see below), we’ll end up with this transformation: <Transformation ldraw="2561.dat" tx="0" ty="-1.72" tz="0.336" ax="-0.3574067443365933" ay="-0.8628562094610169" az="0.3574067443365933" angle="1.7177715174584016"/> How? So, how do we find the right values to have the correct transformations? What’s the ID? Having the right part Check the ID of the part in LDD. Check the ID of the part in LDraw. Beware of variants, LDraw uses a letter suffix (a, b, c…) where LDD totally changes the ID or keeps the same ID for new variants. Don’t hesitate to look on BrickLink for the part ID: BrickLink keeps a list of alternate IDs (when the same part has several IDs) and links to variants and notes. If the IDs are the same. Nothing to do. If the IDs differ. We add a Brick element: <Brick ldraw="123a.dat" lego="456" /> Don’t forget the “.dat”! That was the easy part. Which way is up? Finding the rotation axis and angle We start in LDD. Up is Y, or Y is up. X and Z are a bit harder to see on the LDD scene unless you use LDD’s developper mode (which has the LDD axes drawn at «0,0,0» as red X, green Y, and blue Z lines). Or, if you’re sure you didn’t move the camera in a brand new model/file, X is pointing bottom right, and Z bottom left. We place our part among other parts that we know will be correctly converted (like 1x1 plates, or harpoons ) to have references. Using different colors greatly helps! We export to LDraw… … and look at the results: We decompose the transformation in multiple simple rotations, around the X, Y, or Z axis. If it has been turned around X, a quarter turn from Y to Z is a positive π/2 angle. If it has been turned around Z, a quarter turn from X to Y is a positive π/2 angle. If it has been turned around Y, a quarter turn from Z to X is a positive π/2 angle. To make it short, it’s a direct (right-handed) basis. If you can’t figure out the problems with an existing transformation, “clear” it by using an identity transformation: <transformation tx="0" ty="0 tz="0" ax="0" ay="1" az="0 angle="0"/> (All zeroes but one of the a_ which is 1.) You can try each simple rotation one by one to be sure of their angles (especially their signs ). Beware, combining rotations change their axes (e.g. turning around first X then Y is equivalent to turning around first Y then Z). So if you check that the Y rotation is okay, then the X rotation, don’t forget to combine them as Y then Z. For the musket, we need two rotations: an eighth of a turn (π/4, 45°) around the Z (blue) axis that puts the barrel vertical, and then a quarter turn (-π/2, -90°) around the Y (green) axis. Or we can first make the quarter turn (-π/2, -90°) around the Y (green) axis, and then an eighth of a turn (π/4, 45°) around the X (red) axis. Remember, “import”-wise, we’re trying to find what should happen to the part in the LDD scene to be like the LDraw one, with the LDD axes (the harpoons ). My head is turning. Combining rotations If more than one simple rotation is needed, we have to combine them. For that, we’ll use quaternions. Eh come back! That’s not that difficult! A quaternion q can be written as q = a + b.i + c.j + d.k, where i² = j² = k² = i.j.k = -1 (so i.j = k = -j.i, j.k = i = -k.j, k.i = j = -i.k). a is the real part, b.i + c.j + d.k is the imaginary part. A rotation by the angle angle around the axis «ax, ay, az» is the quaternion q = cos(angle/2) + sin(angle/2).(ax.i + ay.j + az.k) Do note the 1/2 factor on the angle! To combine two rotations, we just multiply their quaternions and apply the rules above to end up with a a + b.i + c.j + d.k form (or, more accurately, a C + S.(ax.i + ay.j + az.k) form, where C and S are cosine and sine of the same angle and ax² + ay² + az² = 1 ). If we rotate first by q and then by p, the result is the rotation by p.q. Note the order: q then p is p.q. Multiplication is not commutative with quaternions: if you do it the wrong way, you’ll end up with the correct values but the wrong signs. There’re lots of fun to have with quaternions and rotations as quaternions. But what is said here is sufficient for our purposes. An example: Most of the times, we do π/2 rotations (quarter turns, 90°). angle = π/2 therefore cos(angle/2) = sin(angle/2) = cos(π/4) = sin(π/4) = √2/2; So, for a “horizontal” quarter turn (yaw, around Y): q = √2/2 + √2/2.j (as j/Y is the “vertical” axis). Let’s combine it with a half turn (π, 180°) around the X axis (IOW, upside-down): cos(π/2) = 0, sin(π/2) = 1, so p = 0 + i p.q = (0 + i) . (√2/2 + √2/2 j) = √2/2 i + √2/2 i.j = 0 + √2/2 ( i + k ) Now, let’s get the resulting angle: The real part of p.q, 0, is the cosine of angle/2. 0 is also the cosine of ±π/2 (±90°). Therefore, the resulting angle is π (180°). Now the axis, «ax, ay, az»: It’s the √2/2( i + k) imaginary part. That’s the vector «√2/2, 0, √2/2». We need to remove the sin(angle/2) factor. That’s easy as the sine of π/2 is 1. So our axis is «ax = √2/2, ay = 0, az = √2/2». Written in ldraw.xml: ax="0.707…" ay="0" az="0.707…" angle="3.1415…" Another one, a quarter turn around Y and then around X: q = √2/2 + √2/2 j = √2/2 (1 + j) p = √2/2 + √2/2 i = √2/2 (1 + i) p.q = 1/2 (1 + i) (1 + j) = 1/2 + 1/2 (i + j + k) We rewrite it as p.q = 1/2 + √3/2 (√⅓ i + √⅓ j + √⅓ k) to have a unit vector (ax² + ay² + az² = 1) in the parenthesis and to clarify the cosine and sine: 1/2 and √3/2. They are the sine and cosine of π/3 (60°). Therefore, the resulting angle is 2π/3 (120°). In ldraw.xml: ax="0.577…" ay="0.577…" az="0.577…" angle="2.094…" Back to our musket: An eighth of a turn (π/4, 45°) around the Z axis that puts the barrel vertical: q = cos(π/8) + sin(π/8).i = C + S.k Then a quarter turn (-π/2, -90°) around the Y axis: p = cos(-π/4) + sin(-π/4).j = √2/2 (1 - j) p.q = √2/2.(1 - j)(C + S.k) = √2/2.(C - S.j.k - C.j + S.k) = √2/2.C + (-√2/2.S.i - √2/2.C.j + √2/2.S.k) Wow! Hum, okay. So √2/2.cos(-π/8) is the cosine of half our angle. Get the calculator out… angle/2 = Acos(√2/2.cos(-π/8)) = 0.8589 Our angle is 1.7178. We “remove” the sine of angle/2 from our vector, so that p.q = cos(angle/2) + sin(angle/2).(ax.i + ay.j + az.k): ax = -√2/2.sin(-π/8) / sin(0.8589) = -0.3574 ay = -√2/2.cos(-π/8) / sin(0.8589) = -0.8629 az = √2/2.sin(-π/8) / sin(0.8589) = 0.3574 As an exercise, you can verify that ax² + ay² + az² = 1. So we did it right! Et voilà: ax="-0.3574067443365933" ay="-0.8628562094610169" az="0.3574067443365933" angle="1.7177715174584016" One step to the left. Getting the translation right Now that the part is correctly oriented, it may need to be moved. The translation is in centimeters (cm). 20 LDU = 0.8 cm. Values are often multiples of 0.4 (half a stud) for tx and tz and multiples of 0.32 (height of a plate) for ty. Other, finer, tunings are often in multiples of 0.008. If the rotation is complex, all bets are off In LDD, we try to place the part so that its LDraw up axis ends up up in the scene, and we try to align its LDraw X and Z axes with X and Z of the scene (at least, that it is not rotated by a weird angle). That way, moving the part along its axes is also moving the part along the scene’s axes. It will be easier for getting the translation right. For our musket, that means the barrel up. (I didn’t align the X and Z axes here because, yeah, I’m a warrior, I don’t need that. Besides, you’ll see what happens because of that. ) Again, I find it easier in LeoCAD: the key bindings, the coordinates clearly shown in the status bar, etc. The thing is, LeoCAD uses a direct Z up basis. So if you move «dx, dy, dz» in LeoCAD, you’re moving «dx, -dz, dy» in LDD (and vice versa). Confusing? Noooh. Anyway, choose your own poison but beware of its little quirks. To help fine tuning, using transparent colors greatly helps, especially for clip-bar connections. Now, we note the coordinates of our part in our LDraw editor and move it so that it ends up the way it should. We look how much we moved it. That’s it! Just convert it to cm (= LDU × 0.8 / 20) and we have our translation. Well, mostly, the signs are wrong. Remember: the transformation is what should happen to the LDD part to end up like the LDraw part, we just did the opposite and moved the LDraw part to be like the LDD one. Besides the signs, if you didn’t correctly align the axes, you’ll have to find which is which For our musket, we need to go up and sligthly to the “left” (from bottom right to upper left when your LDraw view is oriented as a new LDD file, as are all the screenshots here). That means negative dy and dx. But as the part is not aligned on X and Z (but still not badly rotated), the negative dx becomes a positive dz. Et voilà! <Transformation ldraw="2561.dat" tx="0" ty="-1.72" tz="0.336" ax="-0.3574067443365933" ay="-0.8628562094610169" az="0.3574067443365933" angle="1.7177715174584016"/> (So, okay. I had to try first tx then tz, both negative and positive, before I found the right one. But I didn’t want to have to remake the pictures! There: I’m not a warrior, I’m just lazy.)

So it’s easy to know when to blame me.

As of 2016-09-16 and the big overhaul, I assume all the errors. Know Limitations As of LDD 4.3.9, flex parts (hoses) are not exported anymore (even unflexed). Minifig arms and hands are not connected in LDraw. I don’t know whose geometry is off (both?) but the shapes differ a lot. At least, hands are correctly connected to whatever they clip and arms are correctly placed in their sockets and somewhat wrap around the hands’s stems. Some variants are not recognized by LDD (e.g. clips, or tiles with/without groove, etc.) In those cases, I prefer to use the most recent variant in LDraw as it generally is easier to find and cheaper. Sometimes, several LDD parts correspond to a unique LDraw part. Sometimes, the transformation is accurate for one variant but not for another. For example, the Flag 2 x 2 is known to LDD as 2335, 11055, and 60779, but LDraw only has the 2335 variant. 2335 and 60779 use the same transformation but 11055 is vertically offset. I preferred to badly convert 11055 to 2335 rather than not convert it at all or badly convert 2335 and 60779. ldraw.xml is used both ways (LDD to/from LDraw). It’s not something I do frequently (too many resulting collisions) so it’s not well tested. One problem I can see is that, when several LDD parts correspond to a unique LDraw part, the conversion that’s listed last is the one that will be used. The reverse (first written is the one used) is true for assemblies that use the same subparts, in the same quantity (like electric cables). A lot of LDraw parts are simply wrong. Almost all the parts that combine System (studs and anti-studs) and Technic (pins and axles, and their holes) are wrong in that they assume the technic holes are at the same height than side studs (on the picture below, the circles are concentric).

LDD assumes the holes are 0.2 mm (0.5 LDU) higher.

In ABS, the holes are 0.12 mm (0.375 LDU) higher (dixit Jamie Berard in his famous presentation). In order to limit the number and magnitude of errors, LDD is considered to be right. How to write a new transformation for a part in ldraw.xml What? ldraw.xml is an XML file that defines how LDD can export to (or import from) LDraw files. It does so by defining a match between the part’s IDs and how to rotate and translate the part from one geometry to the other. Matches are defined by “Brick” XML elements. For example, this one says to LDD that the Brick 1x1 that it knows as 3005 is also known to LDraw as 3005: <Brick ldraw="3005.dat" lego="3005" /> (Note the “.dat” in the ldraw ID.) Matches are not needed if the part IDs are the same: the transformation element is sufficient for LDD to know the part exists. (So the example above is useless ) Rotations and translations are defined by “Transformation” XML elements. This one says to LDD that the Brick 1x1 just needs to be moved up: <Transformation ldraw="3005.dat" tx="0" ty="-.96" tz="0" ax="1" ay="0" az="0" angle="0" /> The translation (tx, ty, and tz) is in centimeters (0.8 cm is the width of a brick, 0.96 cm its height). The rotation is given by its axis (the line passing through and ), and its angle in radians. And all the coordinates are in the direct (“riht-handed”), Y points up, coordinates system of LDD. The transformation explains what should be done to import from LDraw besides changing the axes (LDD’s Y is up and XYZ is a direct basis, LDraw’s Y is down and XYZ is an indirect basis; so changing the axes only means changing the sign of Y). So, in an LDD to LDraw point of view, the transformation is reversed: it says what happens to a part if you don’t do anything to its coordinates besides changing the sign of Y. In other words, the opposite transformation has to be applied to the LDD coordinates of the part in order to get the LDraw coordinates (with Y reversed). Why? Each part has an orientation (which way up? which way left?) and a center, point of origin, or reference point (we’ll use “reference point” from now on). But LDD and LDraw don’t always agree. To know the orientation and reference point in LDD, insert the part without rotating it nor attaching it to any other part. It will be aligned along the scene’s axes (LDD’s axes). The reference point is near the mouse pointer’s head. To know the orientation and reference point in LDraw, I find LeoCAD the easiest tool: just select the part and its axes are drawn (X red, Y green, Z blue), starting at its reference point. Okay, LeoCAD’s «X, Y, Z» is LDraw’s «X, -Z, Y» but what’s another little change of basis? Sometimes, their disagreement is trivial. For example, for the simple 1x1 brick (3005), both LDD and LDraw agree: the stud is on top and the reference point is on the vertical line going through the center of the stud. But they differ for the height at which the reference point should be: LDD says it’s at the base of the brick, LDraw at its top (but at the base of the stud). (On every picture, X will be red, Y green, and Z blue.) So the transformation for that part is straightforward: if the LDraw part is imported as is, with only Y reversed, it will end up 0.96 cm (the height of the brick) higher than it should. So we have to lower it by 0.96 cm: <Transformation ldraw="3005.dat" tx="0" ty="-.96" tz="0" ax="1" ay="0" az="0" angle="0" /> Sometimes, their disagreement is more profound and the transformation is therefore more complicated. For example, for the musket (Minifig Gun Musket 2561), LDD puts the reference point in the handle and “up” means the handle is vertical but LDraw puts the reference point in the barrel and “up” means the barrel is vertical. Even more, the stock is on the wrong side, so X and Z are different too. With an identity transformation, the part is rotated by an eighth of a turn (X to Y) (π/4) around the Z axis to put the barrel vertical, and then by a quarter turn (X to Z) (-π/2) around the Y axis. After that, it has been translated up and horizontally. After calculations (see below), we’ll end up with this transformation: <Transformation ldraw="2561.dat" tx="0" ty="-1.72" tz="0.336" ax="-0.3574067443365933" ay="-0.8628562094610169" az="0.3574067443365933" angle="1.7177715174584016"/> How? So, how do we find the right values to have the correct transformations? What’s the ID? Having the right part Check the ID of the part in LDD. Check the ID of the part in LDraw. Beware of variants, LDraw uses a letter suffix (a, b, c…) where LDD totally changes the ID or keeps the same ID for new variants. Don’t hesitate to look on BrickLink for the part ID: BrickLink keeps a list of alternate IDs (when the same part has several IDs) and links to variants and notes. If the IDs are the same. Nothing to do. If the IDs differ. We add a Brick element: <Brick ldraw="123a.dat" lego="456" /> Don’t forget the “.dat”! That was the easy part. Which way is up? Finding the rotation axis and angle We start in LDD. Up is Y, or Y is up. X and Z are a bit harder to see on the LDD scene unless you use LDD’s developper mode (which has the LDD axes drawn at «0,0,0» as red X, green Y, and blue Z lines). Or, if you’re sure you didn’t move the camera in a brand new model/file, X is pointing bottom right, and Z bottom left. We place our part among other parts that we know will be correctly converted (like 1x1 plates, or harpoons ) to have references. Using different colors greatly helps! We export to LDraw… … and look at the results: We decompose the transformation in multiple simple rotations, around the X, Y, or Z axis. If it has been turned around X, a quarter turn from Y to Z is a positive π/2 angle. If it has been turned around Z, a quarter turn from X to Y is a positive π/2 angle. If it has been turned around Y, a quarter turn from Z to X is a positive π/2 angle. To make it short, it’s a direct (right-handed) basis. If you can’t figure out the problems with an existing transformation, “clear” it by using an identity transformation: <transformation tx="0" ty="0 tz="0" ax="0" ay="1" az="0 angle="0"/> (All zeroes but one of the a_ which is 1.) You can try each simple rotation one by one to be sure of their angles (especially their signs ). Beware, combining rotations change their axes (e.g. turning around first X then Y is equivalent to turning around first Y then Z). So if you check that the Y rotation is okay, then the X rotation, don’t forget to combine them as Y then Z. For the musket, we need two rotations: an eighth of a turn (π/4, 45°) around the Z (blue) axis that puts the barrel vertical, and then a quarter turn (-π/2, -90°) around the Y (green) axis. Or we can first make the quarter turn (-π/2, -90°) around the Y (green) axis, and then an eighth of a turn (π/4, 45°) around the X (red) axis. Remember, “import”-wise, we’re trying to find what should happen to the part in the LDD scene to be like the LDraw one, with the LDD axes (the harpoons ). My head is turning. Combining rotations If more than one simple rotation is needed, we have to combine them. For that, we’ll use quaternions. Eh come back! That’s not that difficult! A quaternion q can be written as q = a + b.i + c.j + d.k, where i² = j² = k² = i.j.k = -1 (so i.j = k = -j.i, j.k = i = -k.j, k.i = j = -i.k). a is the real part, b.i + c.j + d.k is the imaginary part. A rotation by the angle angle around the axis «ax, ay, az» is the quaternion q = cos(angle/2) + sin(angle/2).(ax.i + ay.j + az.k) Do note the 1/2 factor on the angle! To combine two rotations, we just multiply their quaternions and apply the rules above to end up with a a + b.i + c.j + d.k form (or, more accurately, a C + S.(ax.i + ay.j + az.k) form, where C and S are cosine and sine of the same angle and ax² + ay² + az² = 1 ). If we rotate first by q and then by p, the result is the rotation by p.q. Note the order: q then p is p.q. Multiplication is not commutative with quaternions: if you do it the wrong way, you’ll end up with the correct values but the wrong signs. There’re lots of fun to have with quaternions and rotations as quaternions. But what is said here is sufficient for our purposes. An example: Most of the times, we do π/2 rotations (quarter turns, 90°). angle = π/2 therefore cos(angle/2) = sin(angle/2) = cos(π/4) = sin(π/4) = √2/2; So, for a “horizontal” quarter turn (yaw, around Y): q = √2/2 + √2/2.j (as j/Y is the “vertical” axis). Let’s combine it with a half turn (π, 180°) around the X axis (IOW, upside-down): cos(π/2) = 0, sin(π/2) = 1, so p = 0 + i p.q = (0 + i) . (√2/2 + √2/2 j) = √2/2 i + √2/2 i.j = 0 + √2/2 ( i + k ) Now, let’s get the resulting angle: The real part of p.q, 0, is the cosine of angle/2. 0 is also the cosine of ±π/2 (±90°). Therefore, the resulting angle is π (180°). Now the axis, «ax, ay, az»: It’s the √2/2( i + k) imaginary part. That’s the vector «√2/2, 0, √2/2». We need to remove the sin(angle/2) factor. That’s easy as the sine of π/2 is 1. So our axis is «ax = √2/2, ay = 0, az = √2/2». Written in ldraw.xml: ax="0.707…" ay="0" az="0.707…" angle="3.1415…" Another one, a quarter turn around Y and then around X: q = √2/2 + √2/2 j = √2/2 (1 + j) p = √2/2 + √2/2 i = √2/2 (1 + i) p.q = 1/2 (1 + i) (1 + j) = 1/2 + 1/2 (i + j + k) We rewrite it as p.q = 1/2 + √3/2 (√⅓ i + √⅓ j + √⅓ k) to have a unit vector (ax² + ay² + az² = 1) in the parenthesis and to clarify the cosine and sine: 1/2 and √3/2. They are the sine and cosine of π/3 (60°). Therefore, the resulting angle is 2π/3 (120°). In ldraw.xml: ax="0.577…" ay="0.577…" az="0.577…" angle="2.094…" Back to our musket: An eighth of a turn (π/4, 45°) around the Z axis that puts the barrel vertical: q = cos(π/8) + sin(π/8).i = C + S.k Then a quarter turn (-π/2, -90°) around the Y axis: p = cos(-π/4) + sin(-π/4).j = √2/2 (1 - j) p.q = √2/2.(1 - j)(C + S.k) = √2/2.(C - S.j.k - C.j + S.k) = √2/2.C + (-√2/2.S.i - √2/2.C.j + √2/2.S.k) Wow! Hum, okay. So √2/2.cos(-π/8) is the cosine of half our angle. Get the calculator out… angle/2 = Acos(√2/2.cos(-π/8)) = 0.8589 Our angle is 1.7178. We “remove” the sine of angle/2 from our vector, so that p.q = cos(angle/2) + sin(angle/2).(ax.i + ay.j + az.k): ax = -√2/2.sin(-π/8) / sin(0.8589) = -0.3574 ay = -√2/2.cos(-π/8) / sin(0.8589) = -0.8629 az = √2/2.sin(-π/8) / sin(0.8589) = 0.3574 As an exercise, you can verify that ax² + ay² + az² = 1. So we did it right! Et voilà: ax="-0.3574067443365933" ay="-0.8628562094610169" az="0.3574067443365933" angle="1.7177715174584016" One step to the left. Getting the translation right Now that the part is correctly oriented, it may need to be moved. The translation is in centimeters (cm). 20 LDU = 0.8 cm. Values are often multiples of 0.4 (half a stud) for tx and tz and multiples of 0.32 (height of a plate) for ty. Other, finer, tunings are often in multiples of 0.008. If the rotation is complex, all bets are off In LDD, we try to place the part so that its LDraw up axis ends up up in the scene, and we try to align its LDraw X and Z axes with X and Z of the scene (at least, that it is not rotated by a weird angle). That way, moving the part along its axes is also moving the part along the scene’s axes. It will be easier for getting the translation right. For our musket, that means the barrel up. (I didn’t align the X and Z axes here because, yeah, I’m a warrior, I don’t need that. Besides, you’ll see what happens because of that. ) Again, I find it easier in LeoCAD: the key bindings, the coordinates clearly shown in the status bar, etc. The thing is, LeoCAD uses a direct Z up basis. So if you move «dx, dy, dz» in LeoCAD, you’re moving «dx, -dz, dy» in LDD (and vice versa). Confusing? Noooh. Anyway, choose your own poison but beware of its little quirks. To help fine tuning, using transparent colors greatly helps, especially for clip-bar connections. Now, we note the coordinates of our part in our LDraw editor and move it so that it ends up the way it should. We look how much we moved it. That’s it! Just convert it to cm (= LDU × 0.8 / 20) and we have our translation. Well, mostly, the signs are wrong. Remember: the transformation is what should happen to the LDD part to end up like the LDraw part, we just did the opposite and moved the LDraw part to be like the LDD one. Besides the signs, if you didn’t correctly align the axes, you’ll have to find which is which For our musket, we need to go up and sligthly to the “left” (from bottom right to upper left when your LDraw view is oriented as a new LDD file, as are all the screenshots here). That means negative dy and dx. But as the part is not aligned on X and Z (but still not badly rotated), the negative dx becomes a positive dz. Et voilà! <Transformation ldraw="2561.dat" tx="0" ty="-1.72" tz="0.336" ax="-0.3574067443365933" ay="-0.8628562094610169" az="0.3574067443365933" angle="1.7177715174584016"/> (So, okay. I had to try first tx then tz, both negative and positive, before I found the right one. But I didn’t want to have to remake the pictures! There: I’m not a warrior, I’m just lazy.)