# Converting between world coordinate systems

I have a mesh (verticies, indicies, normals).This mesh uses following world coordinate system:

• Forward: x
• Up: z
• Right: y

I am trying to convert it to a different coordinate system:

• Forward: z
• Up: y
• Right: -x

I swizzled verticies from xzy to zy-x and the geometry looks fine. But the same trick didn't work for normals. What I am missing? Should I use some kind of matrices?

EDIT Red lines - normals vizualization Here is a part of code that shows normals:

GLKVector3 up = GLKVector3Make(0, 0, 1); GLKVector3 normalVec = GLKVector3Make(normalBuffer[i * stride + normalOffset], normalBuffer[i * stride + 1 + normalOffset], normalBuffer[i * stride + 2 + normalOffset]); GLKVector3 axis = GLKVector3Normalize(GLKVector3CrossProduct(up, normalVec)); float dotProduct = GLKVector3DotProduct(up, normalVec); normalNode.rotation = SCNVector4Make(axis.x, axis.y, axis.z, acos(dotProduct));

Every time you interchange two axes, or negate an axis, you mirror space.

So to go from xzy to zy-x we perform:

1. Interchange x & z: zxy (mirrored)

2. Interchange x & y: zyx (unmirrored)

3. Negate x: zy-x (mirrored)

Because we used an odd number of flips, the mesh we have at the end is a mirror image of the one we started with. (That makes sense, since our starting coordinate system was left-handed but our destination is right-handed)

This mirroring means that any faces that had been wound counter-clockwise are now wound clockwise, or vice versa, flipping which side of the surface the renderer thinks is "outside" versus "inside." This can look like a problem with the normals because it affects how the faces get rendered.

To fix this, you can take a pass through all of your triangles and interchange two vertices to reverse the winding order, or flip the direction of backface culling in your render state.

As an aside, it looks like the conversion formula you'd want would look like this:

output.x = -input.y  // left = -right
output.y = input.z   // up = up
output.z = input.x   // forward = forward

• I swapped 2nd and 3rd indicies of every triangle and that fixed the problem with "inverted" surface. But normals are still incorrect. My conversion looks like this GLKVector3Make(-position.y, position.z, position.x). Any ideas? – VenoMKO Apr 27 '18 at 13:22
• Can you show us an example of these incorrect normals? – DMGregory Apr 27 '18 at 13:23
• i'v updated my question – VenoMKO Apr 27 '18 at 13:34
• I had a typo in my code. Now everything is fine. Thanks! One more question. Should i apply same transformation to tangents? – VenoMKO Apr 28 '18 at 5:34

Your mesh should not be in world space. It should be in "object space". It can then be scaled/translated/rotated into world space by homogeneous transform matrices on the GPU.

This includes changes in coordinate system (which, mathematically speaking is exactly the same thing, as a translation).

To do this, you create a 4x4 transform matrix, with the scale component being (-1,1,1), then multiply all other operations by this as a final step:

// right to left ordering
mat4 transform = Othercoordinate * Wscale * Wrotation * Wtranslation
vec4 FinalVertex = transform * ObjectVertex;


// right to left ordering