Recommended Posts

Well, if you don't want to use LDD, you could probably import the lxf file in Studs.io and then export to LDraw again. I don't know how good their import/export quality is though.

Share this post


Link to post
Share on other sites
26 minutes ago, legolijntje said:

I don't know how good their import/export quality is though.

There’re still parts that are not properly imported (wrong position and orientation). And patterns are still lost in translation (as with LDD’s “export to LDR”).

Share this post


Link to post
Share on other sites

I've been meaning to write an LDD importer for a while but I couldn't find any official docs about the file format, is there anything besides your explanation of parts.xml?

Am open source example would be great. :wink:

 

Share this post


Link to post
Share on other sites

I found none. But the LXF format is pretty straightforward (zipped XML + thumbnail). To convert to LDraw, you only need to match part IDs and the coordinates systems. Two things ldraw.xml helps doing :wink:

I guess because LDD does it I never had the idea to write a program to do it, but now that the idea has been planted, I think it would be nice to have one that would handle flexible parts (which are not imported/exported by LDD anymore), even when not-flexed. It would also be nice to handle decors (we would need another conversion table though).

Share this post


Link to post
Share on other sites
16 hours ago, legolijntje said:

Well, if you don't want to use LDD, you could probably import the lxf file in Studs.io and then export to LDraw again. I don't know how good their import/export quality is though.

The program crashed when I loaded the model into Studs.io. 

I found none. But the LXF format is pretty straightforward (zipped XML + thumbnail). To convert to LDraw, you only need to match part IDs and the coordinates systems. Two things ldraw.xml helps doing :wink:

I guess because LDD does it I never had the idea to write a program to do it, but now that the idea has been planted, I think it would be nice to have one that would handle flexible parts (which are not imported/exported by LDD anymore), even when not-flexed. It would also be nice to handle decors (we would need another conversion table though).

I would appreciate it, if there would be be somekind of script or application that allows you convert ldr to lxf files by the press of a button. 

Edited by tomfyhr

Share this post


Link to post
Share on other sites
On 6/5/2017 at 11:30 AM, SylvainLS said:

But the LXF format is pretty straightforward (zipped XML + thumbnail). To convert to LDraw, you only need to match part IDs and the coordinates systems. Two things ldraw.xml helps doing :wink:

Okay, it’s official: I’m dumb(founded). *huh*

I took the coordinates (i.e. position and rotation / or transformation matrix) in a LXF (a couple times the same brick (3005), just rotated and translated), the coordinates (ditto) in the exported LDR, and I can’t find a relation between them (nor their transposed, or inverse, or whatever). It’s the same brick, so the transfomation should be the same each time (and should look like the one in ldraw.xml, modulo a change of basis) *huh*

Share this post


Link to post
Share on other sites

Here’s what I’m talking about: one brick (3005) is placed in LDD, then exported by LDD into an LDraw file. Below are the rotation matrices:

  Rotations         LXF matrix           LDraw matrix
1 none              1,0,0,0,1,0,0,0,1    1,0,0,0,1,0,0,0,1
2 around X          1,0,0,0,0,1,0,-1,0   1,0,0,0,0,-1,0,1,0
3 around Z          0,1,0,-1,0,0,0,0,1   0,1,0,-1,0,0,0,0,1
4 around Y          0,0,1,0,1,0,-1,0,0   0,0,1,0,1,0,-1,0,0
5 around Y then Z   0,-1,0,0,0,1,-1,0,0  0,0,1,1,0,0,0,1,0

1 is placed as-is. 2 is 1 rotated a quarter turn around the X axis (-π/2). 3 = -π/2 around Z. 4 = π/2 around Y. 5 is fisrt rotated π/2 around Y then π/2 around Z.

There’s no rotation needed to go from LXF to LDraw for 3005.dat (only a translation is needed, but it only concerns the positions, not the rotation matrices).

LXF basis is right-handed X-right, Z-front, Y-up. LDraw basis is right-handed X-right, Z-back, Y-down. That is, a rotation of π around the X axis should be needed to change basis.

But:

  1. The “transformed” matrices in LDraw are identical to the ones in LXF for 1, 3, and 4: no transformation (as expected by ldraw.xml) but no change of basis either.
  2. LDR-2 is LDR-1 with a π/2 turn around X, instead of the -π/2 to go from LXF-1 to LXF-2, thus implying a change of basis occured.
  3. LDR-5 corresponds to a π/2 around Z followed by a π/2 around Y, instead of Y then Z. Guh *huh*

So, either I’m missing something obvious (which wouldn’t surprise me :grin: ) or there’s some info missing. Any help appreciated.

Share this post


Link to post
Share on other sites

Have you tried rotating 180 deg around x and flipping x ? This corrects the Y is up/down and right/left handed orientation.

Share this post


Link to post
Share on other sites

The change of basis works fine for the position vector. It’s the rotation matrix that’s giving me a headache.

As I tried to show on the example above, a 3005 1x1 brick just put there (stud up) has a rotation matrix of Identity in LXF and in the generated LDR, with a rotation of 0° in ldraw.xml. ID x ID = ID. If I insert a change of basis in there, it doesn’t work.

Same if the brick is rotated -π/2 around Y, or Z (bricks 3 and 4).

But if the brick is rotated around X (brick 2), then yes, the change of basis is needed (-π/2 becomes π/2).

And if the brick is rotated around Y then Z (brick 5), then it’s totally unrelated to the change of basis.

The LXF is correct. The LDR is correct (the models do look alike). So why do the matrices don’t show a constant relationship? (LXF / LDR should always be the same matrix, no?) (Even 4x4 matrices to account for any affine transformation don’t work. And even if the notations are transposed/inverse (that is, computing t(LXF)/LDR for all bricks), it doesn’t explain the discrepency.)

Share this post


Link to post
Share on other sites

I think you shouldn't split pos and rotation, but use them as a single 4x4 matrix to do the coordinate transformation in one go by using the rotation/flip I wrote above + some scaling in a second static 4x4 matrix.

edit: and re normalize the rotation (3x3) part of the result afterwards. As you only want to scale the positions and not the ldraw parts :)

Wait a minute I misunderstood the problem, I think you should use the LDraw.xml file as parts in LDD have different base orientations  then LDraw parts.

You just need to transpose all those matrices inside LDraw.xml to go from ldr to ldd.

Edited by roland

Share this post


Link to post
Share on other sites

It doesn’t change a thing: to go from the LXF 4x4 matrices to the LDR 4x4 matrices is still not a constant matrix.

Applying the transformations should be Mat_LDR = Mat_basis x Mat_ldraw.xml x Mat_LXF (or the other way around, or the rotation part of Mat_LXF transposed because I don’t know if both notations “a,b,c,d,e,f,g,h,i“ mean ((a b c 0) (d e f 0) (g h i 0) (0 0 0 1)) or its transposed (that is, column-vector or row-vector conventions)). And whatever Mat_basis and Mat_ldraw.xml be, Mat_LXF / Mat_LDR should be constant for the same brick ID (because I don’t see any other information than the brick ID to go from the LXF matrix to the LDR one). It’s not. Never, however I read the data in the LXF and LDR files.

So, something is done beside a change of basis and the ldraw.xml transformation. And I can’t figure what because if it were an affine transformation (translation or rotation or some others), it would be a 4x4 matrix and Mat_LXF / Mat_LDR should still be constant for the same brick ID.

(And I think applying the scale should be easier done on the position only, rather than on all the matrix that I’d have to renormalize afterwards :tongue: )

 

EDIT: just saw your edit (I type slowly).

For now, I was trying to understand how to read the rotation data (row-vector / column vector). So I don’t even use the transformations in ldraw.xml, I’m just trying to check that Mat_LXF / Mat_LDR is constant for the same brick (and, next, how it could relate to what’s in ldraw.xml, but I’m not there). Anyway, the brick I use for the tests, 3005 1x1 brick, only needs to be translated: Its rotation is 0° (because it’s symetric).

Edited by SylvainLS

Share this post


Link to post
Share on other sites

Okay, solved: expressing a rotation matrix R in another basis is R’ = B x R x B⁻¹.

I made several stupid things:

  1. I thought that it was just a matter of combining matrices (that is R’ = B x R).
  2. I didn’t check that assumption.

An the change of basis is just a half turn around X (which is good because it’s equal to its inverse).

So, here’s what’s done in pseudo-code:

# from tx, ty, tz, ax, ay, az, angle in ldraw.xml
lxf2ldr_tr = ( -tx -ty -tz )
lxf2ldr_rot = (( ax*ax*(1-cos)+cos     ax*ay*(1-cos)+az*sin   az*ax*(1-cos)-ay*sin )
               ( ax*ay*(1-cos)-az*sin  ay*ay*(1-cos)+cos      ay*az*(1-cos)+ax*sin )
               ( az*ax*(1-cos)+ay*sin  ay*az*(1-cos)-ax*sin   az*az*(1-cos)+cos    ))
# = the rotation matrix for -angle (ldraw.xml is written “import-wise”, we export)

# read 'a,b,c,d,e,f,g,h,i,x,y,z' in the LXF
lxf_pos = ( x y z )
lxf_rot = (( a d g )
           ( b e h )
           ( c f i ))

# the change of basis (= its inverse)
B = ((1  0  0)
     (0 -1  0)
     (0  0 -1))

# the ldr
rot = lxf_rot * lxf2ldr_rot
ldr_rot = B * rot * B
ldr_pos = B * ( lxf_pos + rot * lxf2ldr_tr ) * 25

# write ldr_pos[0] [1] [2] then ldr_rot[0,0] [0,1] … [2,1] [2,2] (that is "a b c…" for the matrix ((a b c) …))

Now to tackle decorations and flexible parts….

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.