Hi,
currently I'm helping my friend with his master thesis creating 3d airplane simulation, which he will use as presentation {just part of the whole}.
I've got Boening 737-800 model, which is read from obj file format and directly rendered using my simulator program.
The model has many of moving parts, they move independently basing on defined balls. Here's left wing from the top to depict one element and its move logic:
Each moving object {here it is aleiron_left} has two balls: _left and _right which define the horizontal line to rotate around.
I created movement and rotate logic by just using translatef and rotatef, each object is moved independently within its own push and pop matrixes.
Once the project runs I'm able to move the aleiron based on parameter I store in some variable, and it moves alright:
First one is before move, and the second one after move. I added balls for direct reference with 3ds max model.
The balls are also moved using translatef and rotatef using the same move logic, so they are "glued" to their parent part.
Problem is, I need to calculate their world coordinates after move, so in the next step out of the render method I need to obtain direct x,y,z coordinates without again using translatef and rotatef.
I tried to multiply some matrixes and so on, but without result and currently I've got no idea how to do that..
Fragment of code looks like this:
void DrawModel(Model.IModel model)
{
GL.glLoadIdentity();
GL.glPushMatrix();
this.SetSceneByCamera();
foreach (Model.IModelPart part in model.ModelParts)
this.DrawPart(part);
GL.glPopMatrix();
}
void DrawPart(Model.IModelPart part)
{
bool draw = true;
GL.glPushMatrix();
#region get part children
Model.IModelPart child_top = part.GetChild("_top");
Model.IModelPart child_left = part.GetChild("_left");
Model.IModelPart child_right = part.GetChild("_right");
Model.IModelPart child_bottom = part.GetChild("_bottom");
#endregion get part children
#region by part
switch (part.PartTBase)
{
case Model.ModelPart.PartTypeBase.ALEIRON:
{
#region aleiron
float moveBy = 0.0f;
bool selected = false;
switch (part.PartT)
{
case Model.ModelPart.PartType.ALEIRON_L:
{
selected = true;
moveBy = this.GetFromValDic(part);
moveBy *= -1;
}
break;
}
if (selected && child_left != null && child_right != null)
{
GL.glTranslatef(child_right.GetCentralPoint.X, child_right.GetCentralPoint.Y, child_right.GetCentralPoint.Z);
GL.glRotatef(moveBy, child_left.GetCentralPoint.X - child_right.GetCentralPoint.X, child_left.GetCentralPoint.Y - child_right.GetCentralPoint.Y, child_left.GetCentralPoint.Z - child_right.GetCentralPoint.Z);
GL.glTranslatef(-child_right.GetCentralPoint.X, -child_right.GetCentralPoint.Y, -child_right.GetCentralPoint.Z);
}
#endregion aleiron
}
break;
}
#endregion by part
#region draw part
if (!part.Visible)
draw = false;
if (draw)
{
GL.glBegin(GL.GL_TRIANGLES);
for (int i = 0; i < part.ModelPoints.Count; i += 3)
{
if (part.ModelPoints[i].GetTexCoord != null)
GL.glTexCoord3d((double)part.ModelPoints[i].GetTexCoord.X, (double)part.ModelPoints[i].GetTexCoord.Y, (double)part.ModelPoints[i].GetTexCoord.Z);
GL.glVertex3f(part.ModelPoints[i].GetPoint.X, part.ModelPoints[i].GetPoint.Y, part.ModelPoints[i].GetPoint.Z);
if (part.ModelPoints[i + 1].GetTexCoord != null)
GL.glTexCoord3d((double)part.ModelPoints[i + 1].GetTexCoord.X, (double)part.ModelPoints[i + 1].GetTexCoord.Y, (double)part.ModelPoints[i + 1].GetTexCoord.Z);
GL.glVertex3f(part.ModelPoints[i + 1].GetPoint.X, part.ModelPoints[i + 1].GetPoint.Y, part.ModelPoints[i + 1].GetPoint.Z);
if (part.ModelPoints[i + 2].GetTexCoord != null)
GL.glTexCoord3d((double)part.ModelPoints[i + 2].GetTexCoord.X, (double)part.ModelPoints[i + 2].GetTexCoord.Y, (double)part.ModelPoints[i + 2].GetTexCoord.Z);
GL.glVertex3f(part.ModelPoints[i + 2].GetPoint.X, part.ModelPoints[i + 2].GetPoint.Y, part.ModelPoints[i + 2].GetPoint.Z);
}
GL.glEnd();
}
#endregion draw part
GL.glPopMatrix();
}
What happens step by step:
- Prepare scene, set the model camera by current variables {user can move camera using keyboard and mouse in all directions}.
- Take model which contains all modelParts within and draw them one by one. Each part has its own type and subtype set by part name.
- Draw current part independently, get its child_left and child_right -> those are the balls by name.
- Get moveBy value which is angle. Every part has its own variable which is modified using keyboard like "press a, increase variable x for 5.0f", which in turn will rotate aleiron up by 5.0f.
- Move and rotate object by its children
- Draw part triangles {the part has its own list of triangles that are read from obj file}
When I compute the blue ball that is glued to its parent, I do exactly the same so it moves with the same manner:
case Model.ModelPart.PartTypeBase.FLOW:
{
float moveBy = 0.0f;
Model.IModelPart parent = part.GetParent();
if (parent != null)
{
moveBy = this.GetFromValDic(parent);
if (parent.Reverse)
moveBy *= -1.0f;
child_left = parent.GetChild("_left");
child_right = parent.GetChild("_right");
}
if (child_left != null && child_right != null)
{
GL.glGetFloatv(GL.GL_MODELVIEW_MATRIX, part.BeforeMove);
GL.glTranslatef(child_right.GetCentralPoint.X, child_right.GetCentralPoint.Y, child_right.GetCentralPoint.Z);
GL.glRotatef(moveBy, child_left.GetCentralPoint.X - child_right.GetCentralPoint.X, child_left.GetCentralPoint.Y - child_right.GetCentralPoint.Y, child_left.GetCentralPoint.Z - child_right.GetCentralPoint.Z);
GL.glTranslatef(-child_right.GetCentralPoint.X, -child_right.GetCentralPoint.Y, -child_right.GetCentralPoint.Z);
}
}
break;
Before move I read the model matrix using GL.glGetFloatv(GL.GL_MODEL_MATRIX, matrix), which gives me those values {red contains current model camera}:
The blue ball has its own initial central point computed, and currently it is (x, y, z): 339.6048, 15.811758, -166.209473.
As far as I'm concerned, the point world coordinates never change, only its matrix is moved and rotated around some point.
So the final question is, how to calculate the same point world coordinates after the object is moved and rotated?
PS:
to visualize the problem, I've created new small box, which I placed on the center of the blue ball after it is moved upwards.
The position of the box is written by eye - I just placed it couple of times and after x try, I managed to place it correctly using similar world coordinates:
First one is from the left of the box, and the second one is from behind.
The box world coordinates are (x, y, z): 340.745117f, 30.0f, -157.6322f, so according to original central point of blue ball it is a bit higher and closer to the center of the wing.
Simply put, I need to:
- take original central point of blue ball: 339.6048, 15.811758, -166.209473
- after the movement and rotation of the blue ball is finished, apply some algorithm {like take something from modelview_matrix, multiply by something other}
- finally, after the algorithm is complete, in result I get 340.745117f, 30.0f, -157.6322f point {but now computed}, which is the central point in world matrix after movement.
PS2: Sorry for long post, I tried to exactly explain what I'm dealing with.
Thank you in advance for your help.