void cUIMenu::FixMenuPos( eeVector2i& Pos, cUIMenu * Menu, cUIMenu * Parent, cUIMenuSubMenu * SubMenu ) { eeAABB qScreen( 0.f, 0.f, cUIManager::instance()->MainControl()->Size().Width(), cUIManager::instance()->MainControl()->Size().Height() ); eeAABB qPos( Pos.x, Pos.y, Pos.x + Menu->Size().Width(), Pos.y + Menu->Size().Height() ); if ( NULL != Parent && NULL != SubMenu ) { eeVector2i addToPos( 0, 0 ); if ( NULL != SubMenu ) { addToPos.y = SubMenu->Size().Height(); } eeVector2i sPos = SubMenu->Pos(); SubMenu->ControlToScreen( sPos ); eeVector2i pPos = Parent->Pos(); Parent->ControlToScreen( pPos ); eeAABB qParent( pPos.x, pPos.y, pPos.x + Parent->Size().Width(), pPos.y + Parent->Size().Height() ); Pos.x = qParent.Right; Pos.y = sPos.y; qPos.Left = Pos.x; qPos.Right = qPos.Left + Menu->Size().Width(); qPos.Top = Pos.y; qPos.Bottom = qPos.Top + Menu->Size().Height(); if ( !qScreen.Contains( qPos ) ) { Pos.y = sPos.y + SubMenu->Size().Height() - Menu->Size().Height(); qPos.Top = Pos.y; qPos.Bottom = qPos.Top + Menu->Size().Height(); if ( !qScreen.Contains( qPos ) ) { Pos.x = qParent.Left - Menu->Size().Width(); Pos.y = sPos.y; qPos.Left = Pos.x; qPos.Right = qPos.Left + Menu->Size().Width(); qPos.Top = Pos.y; qPos.Bottom = qPos.Top + Menu->Size().Height(); if ( !qScreen.Contains( qPos ) ) { Pos.y = sPos.y + SubMenu->Size().Height() - Menu->Size().Height(); qPos.Top = Pos.y; qPos.Bottom = qPos.Top + Menu->Size().Height(); } } } } else { if ( !qScreen.Contains( qPos ) ) { Pos.y -= Menu->Size().Height(); qPos.Top -= Menu->Size().Height(); qPos.Bottom -= Menu->Size().Height(); if ( !qScreen.Contains( qPos ) ) { Pos.x -= Menu->Size().Width(); qPos.Left -= Menu->Size().Width(); qPos.Right -= Menu->Size().Width(); if ( !qScreen.Contains( qPos ) ) { Pos.y += Menu->Size().Height(); qPos.Top += Menu->Size().Height(); qPos.Bottom += Menu->Size().Height(); } } } } }
void CModelGTF::RenderModel() { // Go through all of the objects stored in this model for(int i = 0; i < m_Model.numOfObjects; i++) { // Get the current object that we are displaying t3DObject *pObject = &m_Model.pObject[i]; // Check if there are materials assigned to this object and // enable texture mapping if necessary, otherwise turn it off. if(pObject->numOfMaterials >= 1) glEnable(GL_TEXTURE_2D); else glDisable(GL_TEXTURE_2D); // Go through all of the faces (polygons) of the object and draw them for(int j = 0; j < pObject->numOfFaces; j++) { // Now let's see if there are any materials that need binding if(pObject->numOfMaterials >= 1) { // Create a static int to hold the last texture ID static int lastTexID = -1; // Extract the current textureID for this face from our face data int textureID = m_Model.pMaterials[pObject->pFaces[j].textureID].texureId; // If the current texture ID isn't the same as last time, bind the texture. if(textureID != lastTexID && textureID >= 0 && textureID < (int)strTextures.size()) glBindTexture(GL_TEXTURE_2D, m_Textures[textureID]); // Store the current textureID in our static int for next time lastTexID = textureID; } // Start drawing our model triangles glBegin(GL_TRIANGLES); // Go through each vertex of the triangle and draw it. for(int whichVertex = 0; whichVertex < 3; whichVertex++) { // Make sure there are texture coordinates for this if(pObject->pTexVerts) { // Here we grab the texture index from our face information int texIndex = pObject->pFaces[j].coordIndex[whichVertex]; // Assign the texture coordinate to this vertex glTexCoord2f(pObject->pTexVerts[ texIndex ].x, pObject->pTexVerts[ texIndex ].y); } // Grab the current vertex index from our face information int vertIndex = pObject->pFaces[j].vertIndex[whichVertex]; //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// // Now we get to the beef of the tutorial. Below is where we // handle the calculations for our animation. Basically what // happens is we grab the current and the next frame of animation // data. With that data (the weights and transformations) we // do spherical interpolation (quaternion rotations) and linear // interpolation (the translations) to get a smooth transformation // between each frame of animation. There isn't anything to // difficult about the concepts, but the math is the challenging // part. The only math that is new to this tutorial is the // calculations of multiplying a quaternion by a 3D vector. // Extract the current vertex and draw it CVector3 vPos = pObject->pVerts[vertIndex]; // If there is no animation, just render the original // vertex and continue (skip the animation calculations). if(!pObject->bAnimated) { glVertex3f(vPos.x, vPos.y, vPos.z); continue; } // This will be our final vertex position to render CVector3 vNewPos(0, 0, 0); // Just to specify the index, we store our vertex index as a blendIndex. // This will index into our weight list. int blendIndex = vertIndex; // Now comes the crazy code :) We now will go through every single // weight influence and add up all the influences and transformations // to our current vertex. for(int b=0; b < pObject->vWeightInfo[blendIndex].numBlendLinks; b++) { // Grab the current bone index from our weight list. Remember that // the X variable stores the bone index and the Y stores the weight. int boneIndex = (int)pObject->vWeightInfo[blendIndex].pWeightInfo[b].x; // Make sure that the index we got isn't out of range of our bones if(boneIndex > pObject->numBones) return; // Now we want to grab the translation and rotation data for both the // current and the next frame of animation. That way we can interpolate // between the two frames to make the animation look smoother. So here // we grab pointers to the current and next matrix information for the // current bone we are working with. tBoneMatrix *pBoneMatrix1 = &(pObject->vBoneInfo[m_Model.currentFrame].pBoneMatrices[boneIndex]); tBoneMatrix *pBoneMatrix2 = &(pObject->vBoneInfo[m_Model.nextFrame].pBoneMatrices[boneIndex]); // First we want to perform the spherical-linear interpolation between // the two quaternions (rotations) for the current and next frame. CQuaternion qPos(pBoneMatrix1->qRotation); CQuaternion qPos2(pBoneMatrix2->qRotation); CQuaternion qNew = qPos.Slerp(qPos, qPos2, m_Model.t); // To apply the interpolated rotation we multiply our rotation by // the original position of the vertex. This will then use our // function that we created at the top of this file which multiplies a // quaternion by a vector. Once we do that, we store the new 3D vector. CVector3 vTempPos = qNew * vPos; // Next we grab the translations for the current and next frame CVector3 vPosition = pBoneMatrix1->vTranslation; CVector3 vNextPosition = pBoneMatrix2->vTranslation; // Using a simple linear-interpolation equation, we use our time "t" // value to interpolate between the current and next translation. This // gives us a smooth transition between each frame of animation. vTempPos.x += vPosition.x + m_Model.t * (vNextPosition.x - vPosition.x); vTempPos.y += vPosition.y + m_Model.t * (vNextPosition.y - vPosition.y); vTempPos.z += vPosition.z + m_Model.t * (vNextPosition.z - vPosition.z); // If there is a special weight for this vertex we want to extract // that and apply it to our current vertex. If the model isn't using // weighted animation then the weight will just be 1.0, which will do // nothing to the vertex when applied. Remember that the Y value of // our weight-info list is the actual weight value to be applied. float weight = pObject->vWeightInfo[blendIndex].pWeightInfo[b].y; // Apply the weight value to our current vertex and add it to our // final transformed vertex position. vNewPos += vTempPos * weight; } // vNewPos has our final position that was transformed, so render it. glVertex3f(vNewPos.x, vNewPos.y, vNewPos.z); //////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// } // Stop drawing polygons glEnd(); } } }