Author Topic: Individual Mesh Rotation  (Read 22899 times)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #30 on: June 10, 2018, 06:18:51 pm »
Thanks Patrice,

I got what you mean.

Let me remind you that the official Wavefront Object format allows us to define three kinds of groups of model components. So far we have ignored them but we can start using some or all of them, if needed. I am not sure if your Cinema 4D .OBJ export plugin can export them but there are at least two other professional 3D editors that support them in full: Autodesk 3ds Max and Maya. And I think AccuTrans can also do this in full or in part even though its usage is very unintuitive and awkward as almost everything else that's been developed in an indie style.

1. Material (mesh) groups:

A group begins at the g somename declaration and includes all the materials (meshes) that follow the initial declaration until the next g anothername declaration or EOF are found in the OBJ file. The original specification doesn't provide for any group parameters but we can augment it with our existing #rotate metadirective written on the line that immediately follows the group declaration in the OBJ file.

If #rotate follows the declaration then not only the mesh centerPoints but also the group's cumulative centerPoint will be calculated and written into each mesh of the group in the MobjMesh rotpoint[x,y,z] arrays.

If a non-grouped mesh should be rotated around its centerPoint as we do our rotations now, then its MobjMesh rotpoint[x,y,z] will duplicate its MobjMat centerPoint[x,y,z] values.

2. Polygon smoothing groups:

We're mostly dealing with models that have their normals precalculated in the editor. If there are no precalculated normals in the model, we're using our own procedure to generate them.

But our procedure is simplistic: it averages normals across the entire model, and as a result we cannot generate so exact and nice looking normals as C4D, 3ds Max or AccuTrans can. They average the normals of polies that fall into their respective smoothing groups only.

A smoothing group begins at the s someindex declaration and includes all the polies that follow the initial declaration until the next s anotherindex declaration or EOF are found in the OBJ file. Indices are usually between 0 and 31, which is sufficient even in very complex models to produce absolutely flat or nicely smoothed normals preserving sharp edges and creases as necessary. Smoothing groups have no default correlation with individual materials (meshes) but may be narrowed down to them if they follow the pattern of material (mesh) declarations.

3. Objects:

An object begins at the o somename declaration and includes everything that follows the initial declaration until the next o anothername declaration or EOF are found in the OBJ file.

The purpose of objects is not fully clear to me but I suspect that they describe multiple individual models placed in a common .OBJ file that in this case acts as the equivalent to a 3D scene.
« Last Edit: June 10, 2018, 06:46:04 pm by Michael Lobko-Lobanovsky »
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Re: Individual Mesh Rotation
« Reply #31 on: June 10, 2018, 06:51:47 pm »
Mike

C4d is dealing with wavefront group, look at any of my .obj model and you will see that the "g group" is already being used for each individual mesh.
« Last Edit: June 10, 2018, 06:53:23 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #32 on: June 10, 2018, 07:02:43 pm »
There must be some C4D model component parameter that the exporter will interpret (if it is smart enough, of course) as an OBJ group, which is in fact a superset of several materials (or "meshes" in C4D parlance), rather than a simple, and thus useless, alias to an ordinary OBJ material (or "mesh" in C4D parlance).

In the Wavefront Object specification, the notions of groups and materials have no correlation and are interpreted as I have described above. A C4D "group" is a mesh, a cluster of model polies, while an OBJ "group" is a cluster of model materials. C4D is built around geometry while OBJ is built around materials.

You will have to edit your OBJ files manually in your Notepad if the C4D OBJ exporter isn't able to adapt its output to OBJ notions and vocabulary rather than its own (wild) interpretation of the same.

P.S. If we proceed as I have described then we will be able to ensure complex animations where individual meshes can rotate around their own center points while being able to concurrently rotate as a group around the group's common center of rotation. 8)
« Last Edit: June 10, 2018, 07:29:28 pm by Michael Lobko-Lobanovsky »
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Re: Individual Mesh Rotation
« Reply #33 on: June 10, 2018, 07:34:09 pm »
I did further investigations, and it seems obvious to me that we have to handle things from the mtl file only, leaving the .obj file untouched.
We could use a new meta #group group_identifier for all meshes belonging to the same group.
And compute the correct group center…

I have attached a project of what we could get...
« Last Edit: June 10, 2018, 07:55:58 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #34 on: June 10, 2018, 07:52:22 pm »
We're drifting farther and farther away from the original Alias Wavefront Object format. We're about to duplicate in our deviant MAT files what's already there in the OBJ file specification -- only because the C4D motherphuckers were not meticulous enough (carelessly or on purpose) to follow the OBJ specs thoroughly.

Another point is you don't want to walk an extra mile and edit the OBJ files manually as you're editing their MAT files. This I can understand too.

But still... ???
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #35 on: June 10, 2018, 08:15:19 pm »
I have attached a project of what we could get...

Or we could have your "time machine" all spinning and glowing pretty much like in the original movie...  :D

OK, do as you like with #group group_identifier but let me test it before you take the final decision to release the next ObjReader build.
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Re: Individual Mesh Rotation
« Reply #36 on: June 10, 2018, 08:24:14 pm »
Quote
OK, do as you like with #group group_identifier but let me test it before you take the final decision to release the next ObjReader build.

No decision taken yet, this is why your feedback is important to me my friend.

However i would say that #rotate is already not a valid Wavefront option, and as far as i know there is no rotation feature in it either.

...
Patrice
(Always working with the latest Windows version available...)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #37 on: June 10, 2018, 09:25:50 pm »
Considering that our current "rotation" doesn't work correctly anyway, please proceed as follows:
  • Use #group group_identifier followed in the next line with #rotate in the .MAT file to unite several meshes into a rotating "group"
  • Adjust our MAT parser to recognize these metacommands but don't add any "group" action code yet
  • Add a rotCenter[2] array in each MobjMesh
  • If an individual mesh is going to #rotate, copy its actual centerPoint[] to rotCenter[]
  • Make your current code work with these fixes and then send it to me.
I will then add a calcGroupCenter() routine that will calc the "group" cumulative center and store it in the individual rotCenter[] arrays of "group" meshes.

Hopefully this is going to work for both the current abnormal "rotation" and future fixups with minimum major code re-writes.
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Re: Individual Mesh Rotation
« Reply #38 on: June 11, 2018, 10:20:56 am »
Mike

Here is the new mobj.h, with the changes you asked for.
Search for the comments: PAT: 06-11-2018

I checked it with Test.obj and it worked fine with the current mtl file.

About the new pMaterial usegroup it must be a unique integer number
all meshes with the same usegroup number will belong to the same group.
My choice is for number, rather than verbose name, for ease of comparison, and smaller code.

Note: The post processing version will be also non-wavefront standard.
But the important thing is that we can keep reading/render a standard .obj file.

However if ever we go for our own binary format, we will use a new .orb file extension…

Added:
Very strange, i just checked using the new meta #group 1, and without doing anything else, i got this result (see the video).
 :o   ::)  ???
« Last Edit: June 11, 2018, 03:01:53 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Re: Individual Mesh Rotation
« Reply #39 on: June 11, 2018, 03:00:47 pm »
Here is the result once the rotating group is combined with the whole model…

That shouldn't be too hard to fix (just using plain negate without the extra trick) ;)
Patrice
(Always working with the latest Windows version available...)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #40 on: June 11, 2018, 03:02:18 pm »
Thank you, Patrice.

Quote
Very strange, i just checked using the new meta #group 1, and without doing anything else, i got this result (see the video).

Sorry but that's too little info for me. I haven't got the model you're showing in the movie and that's why I can't guess what's wrong with what I'm seeing. ;)
_________________________________

Anyway, I've got rotation working correctly using trig and matrix math.

In mobj.h immediately below the existing void billBoard(...) function, copy the following three new functions:
Code: [Select]
__forceinline float dotVec3(float v1[], float v2[]) {
    return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}

__forceinline void mtxTranslate(float* m, float x, float y, float z) // Translate existing matrix by x, y, and z
{
    m[12] += m[0] * x + m[4] * y + m[8]  * z;
    m[13] += m[1] * x + m[5] * y + m[9]  * z;
    m[14] += m[2] * x + m[6] * y + m[10] * z;
}

void mtxRotate(float* m, float x, float y, float z, float deg) // Rotate existing matrix by angle in degrees around x, or y, or z
{
#define d2r .0174533f
    float rad = deg * d2r, s = sin(rad), c = cos(rad), t = 1 - c;
    float v1[] = { x * x * t + c,     x * y * t + z * s, x * z * t - y * s };
    float v2[] = { y * x * t - z * s, y * y * t + c,     y * z * t + x * s };
    float v3[] = { z * x * t + y * s, z * y * t - x * s, z * z * t + c     };

    for (int i = 0; i < 3; i++) {
        float v4[] = { m[0 + i], m[4 + i], m[8 + i] };
        m[0 + i] = dotVec3(v4, v1);
        m[4 + i] = dotVec3(v4, v2);
        m[8 + i] = dotVec3(v4, v3);
    }
#undef d2r
}

and, instead of yours, use the following rotation code in both Mobj_DrawUsingProgrammablePipeline() and Mobj_DrawUsingFixedFuncPipeline():
Code: [Select]
........
            // Test rotation // MLL 06-11-2018:
            if ((pMaterial->rotate[0] != 0.0f) && gP.nRotation) {
                float m[16];
                glPushMatrix();
                pMaterial->rotangle += pMaterial->rotate[0];
                glGetFloatv(GL_MODELVIEW_MATRIX, m);
                mtxTranslate(m, pMesh->centerPoint[0], pMesh->centerPoint[1], pMesh->centerPoint[2]);
                if (pMaterial->rotate[1]) mtxRotate(m, pMaterial->rotate[1], 0, 0, pMaterial->rotangle);
                if (pMaterial->rotate[2]) mtxRotate(m, 0, pMaterial->rotate[2], 0, pMaterial->rotangle);
                if (pMaterial->rotate[3]) mtxRotate(m, 0, 0, pMaterial->rotate[3], pMaterial->rotangle);
                mtxTranslate(m, -pMesh->centerPoint[0], -pMesh->centerPoint[1], -pMesh->centerPoint[2]);
                glLoadMatrixf(m);
            }
........

The code looks somewhat heavy but alas, 3D rotations have never been easy.

Put more spheres in the other quadrants and test if they also behave correctly. Note that rotation preserves the mesh dimensions correctly only when the pMaterial->rotate[1,2,3] values are strictly 1.0f or 0.0f, e.g. #rotate 5, 1, 0, 1. If the array values are other than those two, the mesh exhibits strange scaling effects. But I think you may find them amusing and probably useful too in some of your future implementations. :D
« Last Edit: June 11, 2018, 03:05:50 pm by Michael Lobko-Lobanovsky »
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #41 on: June 11, 2018, 03:17:15 pm »
Test with the existing Tron/test in the meantime.
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Re: Individual Mesh Rotation
« Reply #42 on: June 11, 2018, 04:00:35 pm »
Here is the Helios2 project (put it into the same folder than the original).

Note: Helios2 doesn't work with the changes you have done.
However Tron test, keep working.
« Last Edit: June 11, 2018, 04:19:32 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #43 on: June 11, 2018, 04:15:41 pm »
Patrice,

Please test my code (as it was before your #group changes) with extra balls in the Tron model, and if all the balls rotate correctly, then all models and #group should be made to work with it instead of your old rotation code which was imperfect and spatially incorrect.
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Individual Mesh Rotation
« Reply #44 on: June 11, 2018, 04:24:12 pm »
Patrice,

I don't agree with your #group notation in the MTL file. It is not in the spirit of Wavefront Object format.

I need to zzzZZZ a little but later I'll check your fixes in mobj.h and present my view.
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)