Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre/Tools/3dsmaxExport/LEXIExporter/LexiExport/Sources/LexiIntermediateBuilder.cpp @ 45

Last change on this file since 45 was 6, checked in by anonymous, 18 years ago

=…

File size: 23.1 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of LEXIExporter
4
5Copyright 2006 NDS Limited
6
7Author(s):
8Mark Folkenberg,
9Bo Krohn
10
11This program is free software; you can redistribute it and/or modify it under
12the terms of the GNU Lesser General Public License as published by the Free Software
13Foundation; either version 2 of the License, or (at your option) any later
14version.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
19
20You should have received a copy of the GNU Lesser General Public License along with
21this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22Place - Suite 330, Boston, MA 02111-1307, USA, or go to
23http://www.gnu.org/copyleft/lesser.txt.
24-----------------------------------------------------------------------------
25*/
26
27#include "LexiStdAfx.h"
28#include "LexiIntermediateAPI.h"
29
30//
31
32CIntermediateBuilder::CIntermediateBuilder()
33{
34        m_iBoneIndex = 0;
35        m_fAnimTotalLength=0.0;
36        m_pSkeletonBuilder = NULL;
37}
38
39CIntermediateBuilder::~CIntermediateBuilder()
40{
41        for(std::map<Ogre::String, CIntermediateMaterial*>::iterator it = m_lMaterials.begin(); it != m_lMaterials.end(); it++)
42        {
43                CIntermediateMaterial* pMat = it->second;
44                delete pMat;
45        }
46        m_lMaterials.clear();
47
48        delete m_pSkeletonBuilder;
49}
50
51//
52
53void CIntermediateBuilder::Clear()
54{
55        for(std::map<Ogre::String, CIntermediateMaterial*>::iterator it = m_lMaterials.begin(); it != m_lMaterials.end(); it++)
56        {
57                CIntermediateMaterial* pMat = it->second;
58                delete pMat;
59        }
60        m_lMaterials.clear();
61
62        delete m_pSkeletonBuilder;
63        m_pSkeletonBuilder = NULL;
64}
65
66void CIntermediateBuilder::SetConfig( CDDObject* pConfig )
67{
68        assert(pConfig);
69        m_bExportSkeleton = pConfig->GetBool("SkeletonID", false);
70        m_iAnimStart = pConfig->GetInt("AnimationStartID", 0);
71        m_iAnimEnd = pConfig->GetInt("AnimationEndID", 1);
72        m_fSampleRate = pConfig->GetFloat("AnimationSampleRateID", 1.0);
73        m_sAnimationName = pConfig->GetString("AnimationNameID", "Anim1");
74
75        // Read Animation Settings
76
77        //CDDObject* pAnimContainer = pConfig->GetDDObject("AnimationDataContainer");
78        //assert(pAnimContainer);
79
80        //m_AnimationSetting.m_lSettings.clear();
81
82        //fastvector<const CDDObject*> lAnimList = pAnimContainer->GetDDList("Animations");
83        //while(!lAnimList.empty())
84        //{
85        //      const CDDObject* pCurAnim = lAnimList.pop_back();
86        //      CAnimationSetting curAnimSetting;
87        //      curAnimSetting.m_sAnimName = pCurAnim->GetString("AnimationNameID","NO_NAME");
88        //      curAnimSetting.m_iStartFrame = pCurAnim->GetInt("AnimationStartID",0);
89        //      curAnimSetting.m_iEndFrame = pCurAnim->GetInt("AnimationEndID",100);
90        //      curAnimSetting.m_fSampleRate = pCurAnim->GetFloat("AnimationSampleRateID",1.0);
91        //      curAnimSetting.m_bOptimize = pCurAnim->GetBool("AnimationOptimizeID",true);
92
93
94        //      int iType = pCurAnim->GetInt("AnimationTypeID");
95        //      std::string sType;
96        //      switch(iType)
97        //      {
98        //      case 0:
99        //              sType = "Bone";
100        //              break;
101        //      case 1:
102        //              sType = "Morph";
103        //              break;
104        //      case 2:
105        //              sType = "Pose";
106        //              break;
107        //      default:
108        //              break;
109        //      };
110        //      curAnimSetting.m_sType = sType;
111
112        //      m_AnimationSetting.m_lSettings.push_back(curAnimSetting);
113        //}
114}
115
116
117//
118
119CIntermediateBuilder* CIntermediateBuilder::Get()
120{
121        static CIntermediateBuilder* pIB = new CIntermediateBuilder;
122        return pIB;
123}
124
125//
126
127static void TransformVectors(const Ogre::Matrix4& omat, Ogre::Vector3* pV, unsigned int iCount)
128{
129        CMatrix mat((const CMatrix&)omat);
130        mat.transpose();
131        mat.transformVectors((const CVec3*)pV, (CVec3*)pV, iCount);
132}
133
134static void TransformPoints(const Ogre::Matrix4& omat, Ogre::Vector3* pV, unsigned int iCount)
135{
136        CMatrix mat((const CMatrix&)omat);
137        mat.transpose();
138        mat.transformPoints((const CVec3*)pV, (CVec3*)pV, iCount);
139}
140
141//
142
143static Matrix3 GetTransformFromNode(TimeValue time, INode* pNode)
144{
145        return pNode->GetNodeTM(time);
146}
147
148static bool TMNegParity(const Matrix3& m)
149{
150        return DotProd(CrossProd(m[0], m[1]), m[2]) < 0.0f ? true : false;
151}
152
153static void GetVertexNormal(Mesh* mesh, unsigned int faceNo, RVertex* rv, Ogre::Vector3& vOut)
154{
155        const Face* f = &mesh->faces[faceNo];
156        unsigned int smGroup = f->smGroup;
157        unsigned int numNormals;
158
159        if(rv->rFlags & SPECIFIED_NORMAL)
160        {
161                vOut = (const Ogre::Vector3&)rv->rn.getNormal();
162                return;
163        }
164        else if((numNormals = rv->rFlags & NORCT_MASK) && smGroup)
165        {
166                if(numNormals == 1)
167                {
168                        vOut = (const Ogre::Vector3&)rv->rn.getNormal();
169                        return;
170                }
171                else
172                {
173                        for(unsigned int x = 0; x < numNormals; x++)
174                        {
175                                if(rv->ern[x].getSmGroup() & smGroup)
176                                {
177                                        vOut = (const Ogre::Vector3&)rv->ern[x].getNormal();
178                                        return;
179                                }
180                        }
181                }
182        }
183        else
184        {
185                vOut = (const Ogre::Vector3&)mesh->getFaceNormal(faceNo);
186                return;
187        }
188}
189
190//
191
192CMeshArray* CIntermediateBuilder::BuildMeshArray(unsigned int iNodeID, const char* pszTypeName, TimeValue iTime)
193{
194        INode* pNode = GetNodeFromID(iNodeID);
195        if(!pNode) return NULL;
196
197        CMeshArray* pRtnArray = NULL;
198
199        //
200
201        ObjectState os = pNode->EvalWorldState(iTime, TRUE);
202        Object* pObj = os.obj;
203        if(!pObj) return NULL;
204
205        TriObject* pTri = (TriObject*)pObj->ConvertToType(iTime, Class_ID(TRIOBJ_CLASS_ID, 0));
206        bool bDeleteTri = (pObj != pTri) ? true : false;
207
208        Mesh* pMesh = &pTri->GetMesh();
209
210        const Matrix3& tm = pNode->GetObjTMAfterWSM(iTime);
211        unsigned int wind[3] = { 0, 1, 2 };
212        if(TMNegParity(tm)) { wind[0] = 2; wind[2] = 0; }
213
214        unsigned int iNumTriangles = pMesh->getNumFaces();
215
216        //
217
218        unsigned int iUVIndex = 0;
219        for(unsigned int x = 1; x <= 99; x++)
220        {
221                char temp[32];
222                sprintf(temp, "uv%i", x);
223                if(!strcmp(pszTypeName, temp))
224                {
225                        iUVIndex = x;
226                        break;
227                }
228        }
229
230        //
231
232        if(!strcmp(pszTypeName, "position"))
233        {
234                CVec3Array* pArray = new CVec3Array(iNumTriangles * 3);
235                pRtnArray = pArray;
236
237                unsigned int iVIndex = 0;
238                for(unsigned int x = 0; x < iNumTriangles; x++)
239                {
240                        Face* face = &pMesh->faces[x];
241                        for(unsigned int y = 0; y < 3; y++)
242                        {
243                                const Point3& v = pMesh->verts[face->v[wind[y]]];
244                                (*pArray)[iVIndex++] = Ogre::Vector3(v.x, v.z, -v.y);
245                        }
246                }
247        }
248        else if(!strcmp(pszTypeName, "normal"))
249        {
250                CVec3Array* pArray = new CVec3Array(iNumTriangles * 3);
251                pRtnArray = pArray;
252
253                pMesh->checkNormals(TRUE);
254                Ogre::Vector3 vn;
255
256                unsigned int iVIndex = 0;
257                for(unsigned int x = 0; x < iNumTriangles; x++)
258                {
259                        Face* face = &pMesh->faces[x];
260
261                        for(unsigned int y = 0; y < 3; y++)
262                        {
263                                GetVertexNormal(pMesh, x, pMesh->getRVertPtr(face->v[wind[y]]), vn);
264                                (*pArray)[iVIndex++] = Ogre::Vector3(vn.x, vn.z, -vn.y);
265                        }
266                }
267        }
268        else if(!strcmp(pszTypeName, "diffuse") && pMesh->numCVerts)
269        {
270                CVec4Array* pArray = new CVec4Array(iNumTriangles * 3);
271                pRtnArray = pArray;
272
273                unsigned int iVIndex = 0;
274                for(unsigned int x = 0; x < iNumTriangles; x++)
275                {
276                        TVFace* face = &pMesh->vcFace[x];
277
278                        for(unsigned int y = 0; y < 3; y++)
279                        {
280                                const Point3& vc = pMesh->vertCol[face->t[wind[y]]];
281                                Ogre::Vector4& vColor = (*pArray)[iVIndex++];
282                                // Since Max seems to store the colors in reverse (BGR) order we reveses it again into RGB:
283                                vColor.x = vc.z;
284                                vColor.y = vc.y;
285                                vColor.z = vc.x;
286                                vColor.w = 1.0f;
287                        }
288                }
289        }
290        else if(iUVIndex > 0 && (pMesh->numMaps > iUVIndex))
291        {
292                MeshMap* pMeshMap = &pMesh->maps[iUVIndex];
293                if(pMeshMap && pMeshMap->tv && pMeshMap->tf)
294                {
295                        if(!(pMeshMap->GetFlag(MESHMAP_USED)) )
296                                return NULL;
297
298                        CVec2Array* pArray = new CVec2Array(iNumTriangles * 3);
299                        pRtnArray = pArray;
300
301                        unsigned int iVIndex = 0;
302                        for(unsigned int x = 0; x < iNumTriangles; x++)
303                        {
304                                TVFace* face = &pMeshMap->tf[x];
305
306                                for(unsigned int y = 0; y < 3; y++)
307                                {
308                                        const Point3& tc = pMeshMap->tv[face->t[wind[y]]];
309                                        Ogre::Vector2& vUV = (*pArray)[iVIndex++];
310                                        vUV.x = tc.x;
311                                        vUV.y = 1.0f - tc.y;
312                                }
313                        }
314                }
315        }
316
317        //
318
319        if(bDeleteTri) delete pTri;
320
321        return pRtnArray;
322}
323
324//
325
326Ogre::SceneNode* CIntermediateBuilder::CreateHierarchy(unsigned int iNodeID, bool bRecursive, bool bHidden)
327{
328        LOGDEBUG "CIntermediate::CreateHierarchy() - Main call..");
329        return CreateHierarchy(iNodeID, NULL, bRecursive, bHidden);
330}
331
332Ogre::SceneNode* CIntermediateBuilder::CreateHierarchy(unsigned int iNodeID, Ogre::SceneNode* pParent, bool bRecursive, bool bHidden)
333{
334        LOGDEBUG "CIntermediate::CreateHierarchy() - recursive call..");
335        INode* pRoot = GetNodeFromID(iNodeID);
336        if(!pRoot) return NULL;
337
338        LOGDEBUG "CIntermediate::CreateHierarchy() - Creating Intermediate Mesh");
339
340        CIntermediateMesh* pIMesh = CreateMesh(iNodeID);
341        if(!pIMesh) return NULL;
342
343        m_lIMPool.push_back(pIMesh);
344
345        LOGDEBUG "CIntermediate::CreateHierarchy() - Creating Scenenode");
346
347        Ogre::SceneNode* pSceneNode = new Ogre::SceneNode(NULL, pRoot->GetName());
348        pSceneNode->attachObject(pIMesh);
349
350        //
351        LOGDEBUG "CIntermediate::CreateHierarchy() - Getting transformation");
352
353        Matrix3 mTransform = GetTransformFromNode(0, pRoot);
354
355        INode* pRootParent = pRoot->GetParentNode();
356        if(pRootParent)
357        {
358                Matrix3 mParentT = GetTransformFromNode(0, pRootParent);
359                mParentT.Invert();
360                mTransform = mTransform * mParentT;
361        }
362
363        LOGDEBUG "CIntermediate::CreateHierarchy() - Decomposing");
364
365        // Retrieve orientation and transform into proper coord system
366        Point3 pos;
367        Point3 scale;
368        Quat quat;
369        DecomposeMatrix(mTransform, pos, quat, scale);
370
371        Ogre::Quaternion oquat;
372        oquat.x = quat.x;
373        oquat.y = quat.z;
374        oquat.z = -quat.y;
375        oquat.w = quat.w;
376        Ogre::Vector3 axis;
377        Ogre::Radian w;
378        oquat.ToAngleAxis(w, axis);
379        oquat.FromAngleAxis(-w, axis);
380
381        //CIntermediateBuilder::Rotate90DegreesAroundX(quat);
382        //Ogre::Quaternion oquat;
383        //oquat.x = quat.x;
384        //oquat.y = quat.y;
385        //oquat.z = quat.z;
386        //oquat.w = quat.w;
387
388        pSceneNode->setOrientation(oquat);
389
390        // Transform the position into proper coord system
391        Rotate90DegreesAroundX(pos);
392        pSceneNode->setPosition(Ogre::Vector3(pos.x, pos.y, pos.z));
393
394        // NOTICE! Double tjeck if we really doesn´t need to transfrom the Scale ?
395        //pSceneNode->setScale(Ogre::Vector3(scale.x, scale.z, scale.y));
396        pSceneNode->setScale(Ogre::Vector3(1, 1, 1));
397
398        //
399        LOGDEBUG "CIntermediate::CreateHierarchy() - Add to parent");
400
401        if(pParent) pParent->addChild(pSceneNode);
402
403        if(bRecursive)
404        {
405                unsigned int iNumSubNodes = pRoot->NumberOfChildren();
406                for(unsigned int x = 0; x < iNumSubNodes; x++)
407                {
408                        INode* pSubNode = pRoot->GetChildNode(x);
409                        CreateHierarchy(pSubNode->GetHandle(), pSceneNode, true, bHidden);
410                }
411        }
412
413        return pSceneNode;
414}
415
416void CIntermediateBuilder::CleanUpHierarchy( Ogre::SceneNode* pNode )
417{
418        std::vector<Ogre::MovableObject*> lDeleteThese;
419
420        Ogre::SceneNode::ObjectIterator it = pNode->getAttachedObjectIterator();
421        while(it.hasMoreElements())
422        {
423                Ogre::MovableObject* pObj = it.peekNextValue();
424                lDeleteThese.push_back(pObj);
425                it.moveNext();
426        }
427        for(int i=0; i < lDeleteThese.size(); i++)
428        {
429                pNode->detachObject(lDeleteThese[i]);
430                delete lDeleteThese[i];
431        }
432
433        std::vector<Ogre::SceneNode*> lDeleteTheseNodes;
434
435        Ogre::Node::ChildNodeIterator it2 = pNode->getChildIterator();
436        while(it2.hasMoreElements())
437        {
438                Ogre::SceneNode* pChild = (Ogre::SceneNode*)it2.peekNextValue();
439                CleanUpHierarchy(pChild);
440                lDeleteTheseNodes.push_back(pChild);
441                it2.moveNext();
442        }
443        for(int i=0; i < lDeleteTheseNodes.size(); i++)
444        {
445                pNode->removeChild(lDeleteTheseNodes[i]);
446                delete lDeleteTheseNodes[i];
447        }
448}
449
450CIntermediateMesh* CIntermediateBuilder::CreateMesh(unsigned int iNodeID)
451{
452        LOGDEBUG "Verify Node ID");
453
454        // Verify Node ID
455        INode* pRoot = GetNodeFromID(iNodeID);
456        if(!pRoot) return NULL;
457
458        LOGDEBUG "Get object on node");
459
460        // Retrieve object on node
461        ObjectState os = pRoot->EvalWorldState(0, TRUE);
462        Object* pObj = os.obj;
463        if(!pObj) return NULL;
464
465        LOGDEBUG "Validate");
466
467        // We only use the Mesh objects
468        if(pObj->ClassID() == Class_ID(TARGET_CLASS_ID, 0)) return NULL;
469        if(pObj->SuperClassID() != GEOMOBJECT_CLASS_ID) return NULL;
470        if(!pObj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) return NULL;
471
472        LOGDEBUG "->TRIOBJ_CLASS");
473
474        // Convert object into triangle object (mesh data)
475        TriObject* pTri = (TriObject*)pObj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));
476        if(!pTri) return NULL;
477
478        bool bDeleteTri = (pObj != pTri) ? true : false;
479
480        LOGDEBUG "Get mesh");
481        Mesh* pMesh = &pTri->GetMesh();
482        if(!pMesh || !pMesh->getNumFaces())
483        {
484                if(bDeleteTri) delete pTri;
485                return NULL;
486        }
487
488        // CALL ON_CREATE_INTERMEDIATE_MESH_START()
489       
490        LOGDEBUG "Get material");
491        Mtl* maxMtl = pRoot->GetMtl();
492        if(maxMtl == NULL)
493        {
494                StdMat* pBlankMat = NewDefaultStdMat();
495               
496                pBlankMat->SetDiffuse( Color(1,1,1), 0);
497                Ogre::String name = Ogre::String(pRoot->GetName()) + Ogre::StringConverter::toString(pRoot->GetHandle()) + Ogre::String("_material") ;
498                pBlankMat->SetName( name.c_str() );
499                maxMtl = (Mtl*)pBlankMat;
500        }
501        BOOL bMultiMat = maxMtl->IsMultiMtl();
502
503        LOGDEBUG "Construct intermediate mesh");
504        unsigned int iNumTriangles = pMesh->getNumFaces();
505        CIntermediateMesh* pIMesh = new CIntermediateMesh(iNumTriangles, iNodeID);
506
507        LOGDEBUG "Construct intermediate skeletonbuilder");
508        if(m_pSkeletonBuilder == NULL)
509                m_pSkeletonBuilder = new CIntermediateBuilderSkeleton();
510
511        LOGDEBUG "Build skeleton");
512        m_pSkeletonBuilder->BuildIntermediateSkeleton(pRoot);
513
514        LOGDEBUG "Set skeleton");
515        pIMesh->SetSkeleton( m_pSkeletonBuilder->GetSkeleton() );
516
517        LOGDEBUG "Iterate triangles");
518        //
519        unsigned int iBoneIndex = 0;
520        unsigned int iVIndex = 0;
521        for(unsigned int x = 0; x < iNumTriangles; x++)
522        {
523                // Order the face. Due to flat shading where the
524                // first vertex in a face is used to color the entire face.
525                // So faces in the same polygon should share the same start vertex.
526                //unsigned int wind[3] = { 0, 1, 2 };
527                //if((x%2))
528                //{
529                //      wind[0]=1;
530                //      wind[1]=2; // should be 2,0,1 if we use OpenGL
531                //      wind[2]=0;
532                //}
533
534                const Matrix3& tm = pRoot->GetObjTMAfterWSM(0);
535                unsigned int wind[3] = { 0, 1, 2 };
536                if(TMNegParity(tm)) { wind[0] = 2; wind[2] = 0; }
537
538                // Create a flat indexing to the verticies.
539
540                CTriangle& tri = pIMesh->GetTriangle(x);
541                tri.m_Vertices[wind[0]] = iVIndex++;
542                tri.m_Vertices[wind[1]] = iVIndex++;
543                tri.m_Vertices[wind[2]] = iVIndex++;
544
545                Mtl* pMat = maxMtl;
546                if (bMultiMat)
547                        pMat = maxMtl->GetSubMtl( pMesh->getFaceMtlIndex(x) );
548
549                tri.m_pMaterial = CreateMaterial( pMat );
550
551                // CALL ON_CREATE_INTERMEDIATE_MESH_TRIANGLE_LOOP(pMesh, idx, tri.m_Vertices[wind[j]], x)
552
553                if(m_pSkeletonBuilder != NULL)
554                {
555                        for (int j=0; j<3; j++)
556                        {
557                                // get current index from max mesh
558                                int idx = pMesh->faces[x].v[j]; 
559                                m_pSkeletonBuilder->SetVertexData( idx, tri.m_Vertices[wind[j]] );
560                        }
561                }
562        }
563
564        LOGDEBUG "Finalize");
565        CIntermediateBuilder::Get()->GetSkeletonBuilder()->Finalize();
566
567        LOGDEBUG "CIntermediate::CreateMesh() - Building Material List..");
568
569        pIMesh->BuildMaterialList();
570
571
572        // CALL ON_CREATE_INTERMEDIATE_MESH_END()
573        LOGDEBUG "Delete pTri");
574
575        if(bDeleteTri) delete pTri;
576
577        return pIMesh;
578}
579
580void CIntermediateBuilder::Clamp( Point3& inVec, float threshold )
581{
582        if(inVec.x > 0.0)
583                inVec.x < threshold ? inVec.x = 0 : inVec.x = inVec.x;
584        else
585                inVec.x > -threshold ? inVec.x = 0 : inVec.x = inVec.x;
586
587
588        if(inVec.y > 0.0)
589                inVec.y < threshold ? inVec.y = 0 : inVec.y = inVec.y;
590        else
591                inVec.y > -threshold ? inVec.y = 0 : inVec.y = inVec.y;
592
593
594        if(inVec.z > 0.0)
595                inVec.z < threshold ? inVec.z = 0 : inVec.z = inVec.z;
596        else
597                inVec.z > -threshold ? inVec.z = 0 : inVec.z = inVec.z;
598}
599
600
601
602void CIntermediateBuilder::Rotate90DegreesAroundX( Point3& inVec )
603{
604        // transform nodePos to OgreCoords
605        float negY = -inVec.y;
606        inVec.y = inVec.z;
607        inVec.z = negY;
608}
609
610void CIntermediateBuilder::Rotate90DegreesAroundX( Quat& inQuat )
611{
612        static Quat rotMinus90X = Quat(-sqrt(0.5),0,0,sqrt(0.5));
613        inQuat = rotMinus90X*inQuat;
614}
615
616Ogre::SceneNode* CIntermediateBuilder::CollapseHierarchy(Ogre::SceneNode* pHierarchy, const std::list<std::string>& Arrays, const char* pszName)
617{
618        unsigned int iNumTriangles = 0;
619        CountTriangles(pHierarchy, iNumTriangles);
620
621        //
622        CIntermediateMesh* pMesh = new CIntermediateMesh(iNumTriangles, 0);
623
624        m_lIMPool.push_back( pMesh );
625
626        for(std::list<std::string>::const_iterator it = Arrays.begin(); it != Arrays.end(); it++)
627        {
628                const std::string& sArray = *it;
629                pMesh->ForceCreateArray(sArray.c_str());
630        }
631
632        unsigned int iTriangleOffset = 0;
633        unsigned int iVertexOffset = 0;
634        CollapseHierarchy(pMesh, iTriangleOffset, iVertexOffset, pHierarchy, Arrays, Ogre::Matrix4::IDENTITY);
635
636        //
637        Ogre::SceneNode* pSceneNode = new Ogre::SceneNode(NULL, pszName);
638        pSceneNode->attachObject(pMesh);
639
640        pMesh->m_bIsCollapsed = true;
641
642        return pSceneNode;
643}
644
645void CIntermediateBuilder::CollapseHierarchy(CIntermediateMesh* pMesh, unsigned int& iTriangleOffset, unsigned int& iVertexOffset, Ogre::SceneNode* pNode, const std::list<std::string>& Arrays, const Ogre::Matrix4& mat) const
646{
647        CIntermediateMesh* pNodeMesh = (CIntermediateMesh*)pNode->getAttachedObject(0);
648
649        unsigned int iMatCount = pNodeMesh->m_Materials.size();
650        for(unsigned int x = 0; x < iMatCount; x++)
651        {
652                CIntermediateMaterial* pMat = pNodeMesh->m_Materials[x];
653                bool bMatExists = false;
654
655                unsigned int iMC = pMesh->m_Materials.size();
656                for(unsigned int y = 0; y < iMC; y++)
657                {
658                        if(pMesh->m_Materials[y] == pMat)
659                        {
660                                bMatExists = true;
661                                break;
662                        }
663                }
664
665                if(!bMatExists) pMesh->m_Materials.push_back(pMat);
666        }
667
668        Ogre::Matrix4 om;
669        om.makeTransform(pNode->getPosition(), pNode->getScale(), pNode->getOrientation());
670        Ogre::Matrix4 nmat = mat * om;
671
672        const CTriangleArray& SourceTriangles = pNodeMesh->GetTriangles();
673        CTriangleArray& TargetTriangles = pMesh->GetTriangles();
674
675        unsigned int iNumTriangles = SourceTriangles.Size();
676
677        for(std::list<std::string>::const_iterator it = Arrays.begin(); it != Arrays.end(); it++)
678        {
679                const std::string& sArray = *it;
680
681                const CMeshArray* pSourceArray = pNodeMesh->GetArray(sArray.c_str(), 0);
682                if(!pSourceArray) continue;
683
684                CMeshArray* pTargetArray = pMesh->GetArray(sArray.c_str(), 0);
685                if(!pTargetArray) continue;
686
687                unsigned int iElemSize = pSourceArray->ElementSize();
688                unsigned int iVO = iVertexOffset;
689
690                unsigned char* pTargetBuffer = (unsigned char*)pTargetArray->Data();
691                pTargetBuffer += (iVertexOffset * iElemSize);
692
693                for(unsigned int x = 0; x < iNumTriangles; x++)
694                {
695                        const CTriangle& t = SourceTriangles[x];
696                        for(unsigned int y = 0; y < 3; y++)
697                        {
698                                memcpy(pTargetBuffer, pSourceArray->Data(t.m_Vertices[y]), iElemSize);
699                                pTargetBuffer += iElemSize;
700                        }
701                }
702
703                if(sArray == "position")
704                {
705                        TransformPoints(nmat, (Ogre::Vector3*)pTargetArray->Data(iVertexOffset), iNumTriangles * 3);
706                }
707                else if(sArray == "normal")
708                {
709                        TransformVectors(nmat, (Ogre::Vector3*)pTargetArray->Data(iVertexOffset), iNumTriangles * 3);
710                }
711        }
712
713        //
714
715        for(unsigned int x = 0; x < iNumTriangles; x++)
716        {
717                const CTriangle& st = SourceTriangles[x];
718                CTriangle& tt = TargetTriangles[iTriangleOffset++];
719
720                tt.m_Vertices[0] = iVertexOffset++;
721                tt.m_Vertices[1] = iVertexOffset++;
722                tt.m_Vertices[2] = iVertexOffset++;
723                tt.m_pMaterial = st.m_pMaterial;
724        }
725
726        //
727
728        unsigned int iNumNodes = pNode->numChildren();
729        for(unsigned int x = 0; x < iNumNodes; x++)
730        {
731                Ogre::SceneNode* pSubNode = (Ogre::SceneNode*)pNode->getChild(x);
732                CollapseHierarchy(pMesh, iTriangleOffset, iVertexOffset, pSubNode, Arrays, nmat);
733        }
734}
735
736void CIntermediateBuilder::CountTriangles(Ogre::SceneNode* pNode, unsigned int& iNumTriangles) const
737{
738        CIntermediateMesh* pMesh = (CIntermediateMesh*)pNode->getAttachedObject(0);
739        if(pMesh) iNumTriangles += pMesh->GetNumTriangles();
740
741        unsigned int iNumNodes = pNode->numChildren();
742        for(unsigned int x = 0; x < iNumNodes; x++)
743        {
744                Ogre::SceneNode* pSubNode = (Ogre::SceneNode*)pNode->getChild(x);
745                CountTriangles(pSubNode, iNumTriangles);
746        }
747}
748
749CIntermediateMaterial* CIntermediateBuilder::CreateMaterial( Mtl* pMaxMaterial )
750{
751        // Tjeck to see if it's a Standard material
752        if (pMaxMaterial->ClassID() != Class_ID(DMTL_CLASS_ID, 0))
753        {
754                Ogre::String str("Material ("+Ogre::String(+pMaxMaterial->GetName())+") Not Standard!");
755                LOGWARNING str.c_str());
756                return NULL;
757        }
758
759        Ogre::String matName = pMaxMaterial->GetName();
760        CIntermediateMaterial* newMat = NULL;
761
762        std::map<Ogre::String, CIntermediateMaterial*>::iterator it = m_lMaterials.find(matName);
763        if (it == m_lMaterials.end())
764        {
765                newMat = new CIntermediateMaterial( matName );
766
767                Color col = pMaxMaterial->GetAmbient();
768                newMat->SetAmbientColor( col.r, col.g, col.b );
769
770                col = pMaxMaterial->GetDiffuse();
771                newMat->SetDiffuseColor( col.r, col.g, col.b );
772
773                col = pMaxMaterial->GetSpecular();
774                newMat->SetSpecularColor( col.r, col.g, col.b );
775
776                col = pMaxMaterial->GetSelfIllumColor();
777                newMat->SetEmissiveColor( col.r, col.g, col.b );
778
779                newMat->SetGlosiness( pMaxMaterial->GetShininess() );
780                newMat->SetSpecularLevel( pMaxMaterial->GetShinStr() );
781
782                // Check to see if it's a Standard material
783                if (pMaxMaterial->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
784                {
785                        StdMat* std = (StdMat *)pMaxMaterial;
786                        newMat->Set2Sided( std->GetTwoSided() ? true : false );
787                        newMat->SetWired( std->GetWire() ? true : false );
788
789                        //if (std->ClassID() == Class_ID(DMTL2_CLASS_ID, 0))
790                                newMat->SetFaceted( ((StdMat2 *)std)->IsFaceted() ? true : false );
791
792                }
793
794                RegisterMaps(newMat, pMaxMaterial);
795
796                m_lMaterials.insert( std::pair<Ogre::String, CIntermediateMaterial*>(matName, newMat) );
797        }
798        else
799                newMat = it->second;
800
801        return newMat;
802}
803
804bool CIntermediateBuilder::GetMaterials( std::map<Ogre::String, CIntermediateMaterial*>& materialMap ) const
805{
806        if(m_lMaterials.size() == 0)
807                return false;
808
809        materialMap = m_lMaterials;
810        return true;
811}
812
813void CIntermediateBuilder::RegisterMaps( CIntermediateMaterial* pIMat, Mtl* pMaxMaterial ) 
814{
815        CIntermediateMaterial* newMat = pIMat;
816
817        Ogre::String identifiers[12] = {
818                "ambient_color",
819                "diffuse",
820                "specular_color",
821                "specular_level",
822                "glossiness",
823                "self_illumination",
824                "opacity",
825                "filter_color",
826                "bump",
827                "reflection",
828                "refraction",
829                "displacement"
830        };
831
832        short& mask = pIMat->GetMask();
833
834        Texmap *tmap = NULL;
835        for ( int i=0; i <= 11; i++)
836        {
837                tmap = pMaxMaterial->GetSubTexmap(i);
838                if(tmap == NULL)
839                        continue;
840                if(!((StdMat*)pMaxMaterial)->MapEnabled(i))
841                        continue;
842
843                if(tmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0))
844                {
845                        BitmapTex* pBmt = ((BitmapTex*)tmap);
846                        Ogre::String sMapName = pBmt->GetMapName();
847
848                        STextureMapInfo texInfo;
849                        texInfo.m_sFilename = sMapName;
850                        texInfo.m_sMapType = identifiers[i];
851
852                        if( ((BitmapTex*)tmap)->GetUVWSource()   == UVWSRC_EXPLICIT )
853                                texInfo.m_iCoordSet = pBmt->GetMapChannel();
854                        else
855                        {
856                                texInfo.m_iCoordSet = 1;
857                                // WRITE A WARNING
858                        }
859
860                        StdUVGen* uv = pBmt->GetUVGen();
861                        int uvflags = uv->GetTextureTiling();                           
862
863                        if( ((uvflags & U_WRAP) != 0) || ((uvflags & V_WRAP)!=0) )
864                                texInfo.m_AdressingMode = Ogre::TextureUnitState::TAM_WRAP;
865                        else if( !(uvflags & U_MIRROR) || !(uvflags & U_MIRROR) )
866                                texInfo.m_AdressingMode = Ogre::TextureUnitState::TAM_MIRROR;
867                        else
868                                texInfo.m_AdressingMode = Ogre::TextureUnitState::TAM_CLAMP;
869
870                        // Blend operation is not determined here, but in Ogre-material compiler.
871
872                        texInfo.m_fOffset[0] = uv->GetUOffs(0);
873                        texInfo.m_fOffset[1] = uv->GetVOffs(0);
874
875                        texInfo.m_fScale[0] = uv->GetUScl(0);
876                        texInfo.m_fScale[1] = uv->GetVScl(0);
877
878                        texInfo.m_fAngle = uv->GetAng(0);
879
880                        texInfo.m_fAmount = ((StdMat*)pMaxMaterial)->GetTexmapAmt(i,0);
881
882                        if(pBmt->GetAlphaSource() == ALPHA_FILE)
883                                texInfo.m_bAlpha = true;
884
885                        newMat->AddTextureMap(identifiers[i], texInfo);
886
887                        mask = mask | 1<<i;
888                }
889        }
890}
891
892CIntermediateBuilderSkeleton* CIntermediateBuilder::GetSkeletonBuilder( void )
893{
894        return m_pSkeletonBuilder;
895}
Note: See TracBrowser for help on using the repository browser.