ImpNode* SceneGraphCreator::importInstance( const COLLADAFW::Node* node, INode* parentINode ) { const COLLADAFW::PointerArray<Instance>& instances = (node->*getInstances)(); if ( instances.getCount() != 1 ) return 0; ImpNode* newImportNode = getMaxImportInterface()->CreateNode(); setNodeProperties(node, newImportNode); INode* newNode = newImportNode->GetINode(); Instance* instance = instances[0]; const COLLADAFW::UniqueId& uniqueId = instance->getInstanciatedObjectId(); Object* object = getObjectByUniqueId(uniqueId); if ( object ) { newImportNode->Reference(object); const String& objectName = getObjectNameByObject(object); if ( node->getName().empty() && !objectName.empty() ) { #ifdef UNICODE WideString wideObjectName = COLLADABU::StringUtils::toWideString(objectName.c_str()); newImportNode->SetName( wideObjectName.c_str() ); #else newImportNode->SetName( objectName.c_str() ); #endif } } else { newImportNode->Reference( getDummyObject() ); } const COLLADAFW::UniqueId& instanceGeometryUniqueId = instance->getInstanciatedObjectId(); // Store mapping between unique ids and nodes referencing the corresponding object. // Used to clone nodes addObjectINodeUniqueIdPair(newNode, instanceGeometryUniqueId); // Used to resolve instancing of objects addUniqueIdObjectINodePair(instanceGeometryUniqueId, newNode); parentINode->AttachChild(newNode, FALSE); // post process the creation if ( postProcess ) (this->*postProcess)(newNode, instance); return newImportNode; }
//------------------------------ bool SceneGraphCreator::create() { if ( !mVisualScene ) return false; INode* rootNode = getMaxInterface()->GetRootNode(); //why does this not work: setting rotation on root node // Matrix3 maxTransformationMatrix; // Matrix4ToMaxMatrix3(maxTransformationMatrix, mUpAxisRotation); // rootNode->SetNodeTM(0, maxTransformationMatrix); // // Matrix3 x = rootNode->GetNodeTM(0); if( COLLADABU::Math::Matrix4::IDENTITY != mUpAxisRotation ) { ImpNode* upAxisCorrectionNode = getMaxImportInterface()->CreateNode(); Matrix3 maxTransformationMatrix; Matrix4ToMaxMatrix3( maxTransformationMatrix, mUpAxisRotation ); upAxisCorrectionNode->SetName(__T("upaxis")); upAxisCorrectionNode->SetTransform(0, maxTransformationMatrix); INode* iNode = upAxisCorrectionNode->GetINode(); upAxisCorrectionNode->Reference( getDummyObject() ); rootNode->AttachChild(iNode, FALSE); importNodes(mVisualScene->getRootNodes(), iNode); } else importNodes(mVisualScene->getRootNodes(), rootNode); return true; }
//------------------------------ bool SceneGraphCreator::recursivelyCloneINode( ImpNode* parentImportNode, INode* nodeToClone ) { ImpNode* newImportNode = getMaxImportInterface()->CreateNode(); getMaxImportInterface()->AddNodeToScene(newImportNode); INode* newNode = newImportNode->GetINode(); Object* object = nodeToClone->GetObjectRef(); newImportNode->Reference(object); newNode->SetTMController(nodeToClone->GetTMController()); newImportNode->SetName(nodeToClone->GetName()); //used to assign material addClonedINodeOriginalINodePair(newNode, nodeToClone); INode* parentNode = parentImportNode->GetINode(); parentNode->AttachChild(newNode, TRUE); /* If the node to clone references an object, the cloned one must references the same object.*/ COLLADAFW::UniqueId id = getUniqueIdByObjectINode(nodeToClone); if ( id.isValid() ) { addUniqueIdObjectINodePair(id, newNode); addObjectINodeUniqueIdPair(newNode, id); } // Clone the children for ( int i = 0, count = nodeToClone->NumberOfChildren(); i < count; ++i) recursivelyCloneINode(newImportNode, nodeToClone->GetChildNode(i)); return true; }
INode* WMOGroupImpl::createGroupHeaderNode() { DummyObject* obj = (DummyObject*)CreateInstance(HELPER_CLASS_ID, Class_ID(DUMMY_CLASS_ID, 0)); ImpNode* node = m_wmoImporter->m_impInterface->CreateNode(); node->Reference(obj); node->SetName(m_groupName.c_str()); m_wmoImporter->m_impInterface->AddNodeToScene(node); return node->GetINode(); }
int OBJImport::DoImport(const TCHAR *filename,ImpInterface *i,Interface *gi, BOOL suppressPrompts) { TriObject *object = CreateNewTriObject(); if(!object) return 0; if(objFileRead(filename, &object->GetMesh())) { ImpNode *node = i->CreateNode(); if(!node) { delete object; return 0; } Matrix3 tm; tm.IdentityMatrix(); node->Reference(object); node->SetTransform(0,tm); i->AddNodeToScene(node); node->SetName(GetString(IDS_TH_WAVE_OBJ_NAME)); i->RedrawViews(); return 1; } return 0; }
bool NifImporter::ImportMesh(NiTriStripsRef triStrips) { bool ok = true; ImpNode *node = i->CreateNode(); if(!node) return false; INode *inode = node->GetINode(); TriObject *triObject = CreateNewTriObject(); node->Reference(triObject); wstring name = wide(triStrips->GetName()); node->SetName(name.c_str()); // Texture Mesh& mesh = triObject->GetMesh(); NiTriStripsDataRef triStripsData = DynamicCast<NiTriStripsData>(triStrips->GetData()); if (triStripsData == NULL) return false; vector<Triangle> tris = triStripsData->GetTriangles(); ok |= ImportMesh(node, triObject, triStrips, triStripsData, tris); return ok; }
int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL suppressPrompts) { IfcGeom::IteratorSettings settings; settings.use_world_coords() = false; settings.weld_vertices() = true; settings.sew_shells() = true; #ifdef _UNICODE int fn_buffer_size = WideCharToMultiByte(CP_UTF8, 0, name, -1, 0, 0, 0, 0); char* fn_mb = new char[fn_buffer_size]; WideCharToMultiByte(CP_UTF8, 0, name, -1, fn_mb, fn_buffer_size, 0, 0); #else const char* fn_mb = name; #endif IfcGeom::Iterator<float> iterator(settings, fn_mb); if (!iterator.initialize()) return false; itfc->ProgressStart(_T("Importing file..."), TRUE, fn, NULL); MtlBaseLib* mats = itfc->GetSceneMtls(); int slot = mats->Count(); std::map<std::vector<std::string>, Mtl*> material_cache; do{ const IfcGeom::TriangulationElement<float>* o = static_cast<const IfcGeom::TriangulationElement<float>*>(iterator.get()); TSTR o_type = S(o->type()); TSTR o_guid = S(o->guid()); Mtl *m = ComposeMultiMaterial(material_cache, mats, itfc, slot, o->geometry().materials(), o->type(), o->geometry().material_ids()); TriObject* tri = CreateNewTriObject(); const int numVerts = o->geometry().verts().size()/3; tri->mesh.setNumVerts(numVerts); for( int i = 0; i < numVerts; i ++ ) { tri->mesh.setVert(i,o->geometry().verts()[3*i+0],o->geometry().verts()[3*i+1],o->geometry().verts()[3*i+2]); } const int numFaces = o->geometry().faces().size()/3; tri->mesh.setNumFaces(numFaces); bool needs_default = std::find(o->geometry().material_ids().begin(), o->geometry().material_ids().end(), -1) != o->geometry().material_ids().end(); typedef std::pair<int, int> edge_t; std::set<edge_t> face_boundaries; for(std::vector<int>::const_iterator it = o->geometry().edges().begin(); it != o->geometry().edges().end();) { const int v1 = *it++; const int v2 = *it++; const edge_t e((std::min)(v1, v2), (std::max)(v1, v2)); face_boundaries.insert(e); } for( int i = 0; i < numFaces; i ++ ) { const int v1 = o->geometry().faces()[3*i+0]; const int v2 = o->geometry().faces()[3*i+1]; const int v3 = o->geometry().faces()[3*i+2]; const edge_t e1((std::min)(v1, v2), (std::max)(v1, v2)); const edge_t e2((std::min)(v2, v3), (std::max)(v2, v3)); const edge_t e3((std::min)(v3, v1), (std::max)(v3, v1)); const bool b1 = face_boundaries.find(e1) != face_boundaries.end(); const bool b2 = face_boundaries.find(e2) != face_boundaries.end(); const bool b3 = face_boundaries.find(e3) != face_boundaries.end(); tri->mesh.faces[i].setVerts(v1, v2, v3); tri->mesh.faces[i].setEdgeVisFlags(b1, b2, b3); MtlID mtlid = o->geometry().material_ids()[i]; if (needs_default) { mtlid ++; } tri->mesh.faces[i].setMatID(mtlid); } tri->mesh.buildNormals(); // Either use this or undefine the FACESETS_AS_COMPOUND option in IfcGeom.h to have // properly oriented normals. Using only the line below will result in a consistent // orientation of normals accross shells, but not always oriented towards the // outside. // tri->mesh.UnifyNormals(false); tri->mesh.BuildStripsAndEdges(); tri->mesh.InvalidateTopologyCache(); tri->mesh.InvalidateGeomCache(); ImpNode* node = impitfc->CreateNode(); node->Reference(tri); node->SetName(o_guid); node->GetINode()->Hide(o->type() == "IfcOpeningElement" || o->type() == "IfcSpace"); if (m) { node->GetINode()->SetMtl(m); } const std::vector<float>& matrix_data = o->transformation().matrix().data(); node->SetTransform(0,Matrix3 ( Point3(matrix_data[0],matrix_data[1],matrix_data[2]),Point3(matrix_data[3],matrix_data[4],matrix_data[5]), Point3(matrix_data[6],matrix_data[7],matrix_data[8]),Point3(matrix_data[9],matrix_data[10],matrix_data[11]) )); impitfc->AddNodeToScene(node); itfc->ProgressUpdate(iterator.progress(), true, _T("")); } while (iterator.next()); itfc->ProgressEnd(); return true; }
bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeomRef>& glist) { bool ok = true; if (glist.empty()) return false; ImpNode *node = i->CreateNode(); if(!node) return false; INode *inode = node->GetINode(); TriObject *triObject = CreateNewTriObject(); node->Reference(triObject); string name = parent->GetName(); node->SetName(wide(name).c_str()); // Texture Mesh& mesh = triObject->GetMesh(); vector< pair<int, int> > vert_range, tri_range; vector<Triangle> tris; vector<Vector3> verts; int submats = glist.size(); // Build list of vertices and triangles. Optional components like normals will be handled later. for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) { NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData()); // Get verts and collapse local transform into them int nVertices = triGeomData->GetVertexCount(); vector<Vector3> subverts = triGeomData->GetVertices(); Matrix44 transform = (*itr)->GetLocalTransform(); //Apply the transformations if (transform != Matrix44::IDENTITY) { for ( unsigned int i = 0; i < subverts.size(); ++i ) subverts[i] = transform * subverts[i]; } vert_range.push_back( pair<int,int>( verts.size(), verts.size() + subverts.size()) ); verts.insert(verts.end(), subverts.begin(), subverts.end()); vector<Triangle> subtris = triGeomData->GetTriangles(); for (vector<Triangle>::iterator itr = subtris.begin(), end = subtris.end(); itr != end; ++itr) { (*itr).v1 += nVertices, (*itr).v2 += nVertices, (*itr).v3 += nVertices; } tri_range.push_back( pair<int,int>( tris.size(), tris.size() + subtris.size()) ); tris.insert(tris.end(), subtris.begin(), subtris.end()); } // Transform up-to-parent Matrix44 baseTM = (importBones) ? Matrix44::IDENTITY : parent->GetWorldTransform(); node->SetTransform(0,TOMATRIX3(baseTM)); // Set vertices and triangles mesh.setNumVerts(verts.size()); mesh.setNumTVerts(verts.size(), TRUE); for (int i=0, n=verts.size(); i < n; ++i){ Vector3 &v = verts[i]; mesh.verts[i].Set(v.x, v.y, v.z); } mesh.setNumFaces(tris.size()); mesh.setNumTVFaces(tris.size()); for (int submat=0; submat<submats; ++submat) { int t_start = tri_range[submat].first, t_end = tri_range[submat].second; for (int i=t_start; i<t_end; ++i) { Triangle& t = tris[i]; Face& f = mesh.faces[i]; f.setVerts(t.v1, t.v2, t.v3); f.Show(); f.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS); f.setMatID(-1); TVFace& tf = mesh.tvFace[i]; tf.setTVerts(t.v1, t.v2, t.v3); } } mesh.buildNormals(); bool bSpecNorms = false; MultiMtl *mtl = NULL; int igeom = 0; for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr, ++igeom) { NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData()); int v_start = vert_range[igeom].first, v_end = vert_range[igeom].second; int t_start = tri_range[igeom].first, t_end = tri_range[igeom].second; // Normals vector<Vector3> subnorms = triGeomData->GetNormals(); Matrix44 rotation = (*itr)->GetLocalTransform().GetRotation(); if (rotation != Matrix44::IDENTITY) { for ( unsigned int i = 0; i < subnorms.size(); ++i ) subnorms[i] = rotation * subnorms[i]; } if (!subnorms.empty()) { #if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 // Initialize normals if necessary if (!bSpecNorms) { bSpecNorms = true; mesh.SpecifyNormals(); MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (NULL != specNorms) { specNorms->BuildNormals(); //specNorms->ClearAndFree(); //specNorms->SetNumFaces(tris.size()); //specNorms->SetNumNormals(n.size()); } } MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (NULL != specNorms) { Point3* norms = specNorms->GetNormalArray(); for (int i=0, n=subnorms.size(); i<n; i++){ Vector3& v = subnorms[i]; norms[i+v_start] = Point3(v.x, v.y, v.z); } //MeshNormalFace* pFaces = specNorms->GetFaceArray(); //for (int i=0; i<tris.size(); i++){ // Triangle& tri = tris[i]; // MeshNormalFace& face = pFaces[i+t_start]; // face.SpecifyNormalID(0, tri.v1); // face.SpecifyNormalID(1, tri.v2); // face.SpecifyNormalID(2, tri.v3); //} #if VERSION_3DSMAX > ((7000<<16)+(15<<8)+0) // Version 7+ specNorms->SetAllExplicit(true); #endif specNorms->CheckNormals(); } #endif } // uv texture info if (triGeomData->GetUVSetCount() > 0) { vector<TexCoord> texCoords = triGeomData->GetUVSet(0); for (int i=0, n = texCoords.size(); i<n; ++i) { TexCoord& texCoord = texCoords[i]; mesh.tVerts[i+v_start].Set(texCoord.u, (flipUVTextures) ? 1.0f-texCoord.v : texCoord.v, 0); } } vector<Color4> cv = triGeomData->GetColors(); ImportVertexColor(inode, triObject, tris, cv, v_start); if ( StdMat2* submtl = ImportMaterialAndTextures(node, (*itr)) ) { if (mtl == NULL) { mtl = NewDefaultMultiMtl(); gi->GetMaterialLibrary().Add(mtl); inode->SetMtl(mtl); } // SubMatIDs do not have to be contiguous so we just use the offset mtl->SetSubMtlAndName(igeom, submtl, submtl->GetName()); for (int i=t_start; i<t_end; ++i) mesh.faces[i].setMatID(igeom); } if (enableSkinSupport) ImportSkin(node, (*itr)); } this->i->AddNodeToScene(node); inode = node->GetINode(); inode->EvalWorldState(0); for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) { // attach child if (INode *parent = GetNode((*itr)->GetParent())) parent->AttachChild(inode, 1); inode->Hide((*itr)->GetVisibility() ? FALSE : TRUE); } if (removeDegenerateFaces) mesh.RemoveDegenerateFaces(); if (removeIllegalFaces) mesh.RemoveIllegalFaces(); if (weldVertices) WeldVertices(mesh); if (enableAutoSmooth) mesh.AutoSmooth(TORAD(autoSmoothAngle), FALSE, FALSE); return ok; }
bool PlasmaImport::IImportObject(plSceneObject *obj, ImpInterface *imp) { if (!obj->getDrawInterface().isLoaded()) return false; plDrawInterface* draw = plDrawInterface::Convert(obj->getDrawInterface()->getObj()); plCoordinateInterface* coord = NULL; if (obj->getCoordInterface().Exists()) coord = plCoordinateInterface::Convert(obj->getCoordInterface()->getObj()); TriObject *maxObj = CreateNewTriObject(); Mesh *msh = &maxObj->GetMesh(); std::vector<Point3> vertexList; std::vector<int> indexList; if (!maxObj) return false; // read the object from PRP for (size_t i = 0; i < draw->getNumDrawables(); i++) { if (draw->getDrawableKey(i) == -1) continue; plDrawableSpans* span = plDrawableSpans::Convert(draw->getDrawable(i)->getObj()); plDISpanIndex di = span->getDIIndex(draw->getDrawableKey(i)); if ((di.fFlags & plDISpanIndex::kMatrixOnly) != 0) continue; for (size_t idx = 0; idx < di.fIndices.size(); idx++) { plIcicle* ice = (plIcicle*)span->getSpan(di.fIndices[idx]); std::vector<plGBufferVertex> verts = span->getVerts(ice); std::vector<unsigned short> indices = span->getIndices(ice); for (size_t j = 0; j < verts.size(); j++) { hsVector3 pos; if (coord != NULL) pos = coord->getLocalToWorld().multPoint(verts[j].fPos) * 10.0f; else pos = ice->getLocalToWorld().multPoint(verts[j].fPos) * 10.0f; vertexList.push_back(Point3(pos.X, pos.Y, pos.Z)); } indexList.insert(indexList.end(), indices.begin(), indices.end()); } } //create the Mesh msh->setNumVerts(vertexList.size()); msh->setNumFaces(indexList.size()/3); for (size_t i = 0; i < vertexList.size(); i++) msh->setVert(i, vertexList[i]); for (size_t i = 0; i < indexList.size()/3; i++) { int v1, v2, v3; v1 = indexList[3*i]; v2 = indexList[3*i+1]; v3 = indexList[3*i+2]; msh->faces[i].setVerts(v1, v2, v3); msh->faces[i].setEdgeVisFlags(1,1,1); //we asume we have Triangles obnly } msh->buildNormals(); msh->buildBoundingBox(); msh->InvalidateEdgeList(); //Add Object To Scene ImpNode *node = imp->CreateNode(); Matrix3 tm; tm.IdentityMatrix(); node->Reference(maxObj); node->SetTransform(0,tm); imp->AddNodeToScene(node); node->SetName(obj->getKey()->getName()); imp->RedrawViews(); return true; }
BOOL AIShapeImport::FinishWorkingShape(BOOL forceFinish, ImpInterface *i) { // If nothing going on, forget the whole thing and return success if(!splShape) return TRUE; if(!shape) { assert(0); return FALSE; } // Otherwise, see if the current spline is closed if(spline) { int knots = spline->KnotCount(); // If not a valid spline, get rid of it! if(knots < 2) { singularity: // DebugPrint("WARN: spline w/%d points\n",knots); shape->UpdateSels(); // Make sure it readies the selection set info shape->DeleteSpline(shape->SplineCount() - 1); spline = NULL; } else { int lastKnot = knots-1; if(spline->GetKnotPoint(0) == spline->GetKnotPoint(lastKnot)) { spline->SetInVec(0, spline->GetInVec(lastKnot)); spline->DeleteKnot(lastKnot); if(spline->KnotCount() < 2) goto singularity; spline->SetClosed(); } // Check to be sure knot types are correct -- The default is for // smooth beziers, but they may be corners for(int k = 0; k < knots; ++k) { Point3 in = spline->GetInVec(k); Point3 out = spline->GetOutVec(k); Point3 knot = spline->GetKnotPoint(k); int type = spline->GetKnotType(k); if(type == KTYPE_BEZIER) { if(in == knot && out == knot) // If both zero length vector, it's a corner spline->SetKnotType(k, KTYPE_CORNER); else // If vectors not collinear, it's a corner! if(in == knot || out == knot) // If zero length vector, it's a bez corner spline->SetKnotType(k, KTYPE_BEZIER_CORNER); else { // If vectors not collinear, it's a corner! Point3 normIn = Normalize(knot - in); Point3 normOut = Normalize(out - knot); Point3 lowtest = normIn * 0.98f; Point3 hightest = normIn * 1.02f; if(!(((normOut.x >= lowtest.x && normOut.x <= hightest.x) || (normOut.x <= lowtest.x && normOut.x >= hightest.x)) && ((normOut.y >= lowtest.y && normOut.y <= hightest.y) || (normOut.y <= lowtest.y && normOut.y >= hightest.y)) && ((normOut.z >= lowtest.z && normOut.z <= hightest.z) || (normOut.z <= lowtest.z && normOut.z >= hightest.z)))) spline->SetKnotType(k, KTYPE_BEZIER_CORNER); } } } spline->ComputeBezPoints(); } } // If necessary, create the object if(importType == MULTIPLE_SHAPES || forceFinish) { if(shape->SplineCount()) { shape->UpdateSels(); // Make sure it readies the selection set info shape->InvalidateGeomCache(); // create shape object ImpNode *node = i->CreateNode(); if(!node) return FALSE; node->Reference(splShape); Matrix3 tm(1); Box3 bbox = shape->GetBoundingBox(); Point3 center = Point3(bbox.Center().x, bbox.Center().y, 0.0f); tm.SetTrans(center); // TH 7/5/96 node->SetPivot(-center); // TH 3/9/99 node->SetTransform(0,tm); i->AddNodeToScene(node); TSTR name; name.printf(GetString(IDS_TH_SHAPE_NUM),theShapeImport->shapeNumber++); node->SetName(name); gotStuff = TRUE; } // Reset the shape stuff splShape = NULL; shape = NULL; spline = NULL; } return TRUE; }
BOOL objFileRead(const TCHAR *filename, ImpInterface *imp){ FILE *fp; int i; tLump *idxtable; if((fp = fopen(filename, "rb")) == NULL) return 0; fseek(fp, 0, SEEK_END); int fileSize = ftell(fp); fseek(fp, 0, SEEK_SET); char *data = new char[fileSize]; fread(data, fileSize, 1, fp); tHeader *header = (tHeader *)data; if(*(int*)header->strID != CMAPHEADER_ID) return 0; if(header->version != CMAPHEADER_VERSION) return 0; idxtable = (tLump *)header + 1; tVertex *Verts = (tVertex *)(data + idxtable[kVertices].offset); int NumVerts = idxtable[kVertices].length / sizeof(tVertex); tFace *faces = (tFace *)(data + idxtable[kLeafFaces].offset); int NumFaces = idxtable[kLeafFaces].length / sizeof(tFace); int *elems = (int *)(data + idxtable[kElements].offset); int NumElems = idxtable[kElements].length / sizeof(int); tArea *mAreas = (tArea *)(data + idxtable[kAreas].offset); int NumAreas = idxtable[kAreas].length / sizeof(tArea); Point3 p; TriObject *object = CreateNewTriObject(); if(!object) return 0; Mesh *msh = &object->GetMesh(); msh->setNumVerts(NumVerts); for(i = 0 ; i < NumVerts ; i++){ msh->setVert(i, Verts[i].point[0], -Verts[i].point[2], Verts[i].point[1]); p.Set(Verts[i].norm[0], -Verts[i].norm[2], Verts[i].norm[1]); msh->setNormal(i, p); } int face = 0; for(int k = 1 ; k < NumAreas ; k++){ for(i = mAreas[k].startFace ; i < mAreas[k].startFace + mAreas[k].numOfFaces ; i++){ for(int j = faces[i].startElement ; j < faces[i].startElement + faces[i].elementsSize ; j++){ int k = j * 3; if(elems[k] < 0){ elems[k] = 0; elems[k+1] = 1; elems[k+2] = 2; faces[i].vertexIndex = 0; } msh->setNumFaces(face + 1, TRUE); msh->faces[face].setVerts(faces[i].vertexIndex + elems[k + 0], faces[i].vertexIndex + elems[k + 1], faces[i].vertexIndex + elems[k + 2]); msh->faces[face].setEdgeVisFlags(1, 1, 1); face++; } } } delete [] data; fclose(fp); msh->buildNormals(); msh->buildBoundingBox(); msh->InvalidateEdgeList(); ImpNode *node = imp->CreateNode(); if(!node) { delete object; return 0; } Matrix3 tm; tm.IdentityMatrix(); node->Reference(object); node->SetTransform(0,tm); imp->AddNodeToScene(node); node->SetName(_T("Sylphis map")); return TRUE; }
// 2. 加载骨骼数据 void M2Importer::importBoneObject() { // Bone Group Header Node INode* groupHeadNode = createGroupHeaderNode(); groupHeadNode->SetGroupHead(TRUE); groupHeadNode->SetGroupMember(FALSE); if (m_modelHeader->nameLength > 1) { TCHAR* modelName = (TCHAR*)(m_m2FileData + m_modelHeader->nameOfs); TCHAR boneGroupName[256]; sprintf(boneGroupName, "%s_bone", modelName); groupHeadNode->SetName(boneGroupName); } else groupHeadNode->SetName("BoneGroup"); // Bone // 一个Bone构造一个Node, 并且加入到组中 ModelBoneDef* boneData = (ModelBoneDef*)(m_m2FileData + m_modelHeader->ofsBones); m_boneNodeList.reserve(m_modelHeader->nBones); for (unsigned int i = 0; i < m_modelHeader->nBones; ++i) { ModelBoneDef& boneDef = boneData[i]; // create bone node HelperObject* obj = (HelperObject*)CreateInstance(HELPER_CLASS_ID, Class_ID(BONE_CLASS_ID, 0)); ImpNode* node = m_impInterface->CreateNode(); TCHAR boneName[256]; sprintf(boneName, "bone_%02d", i); node->SetName(boneName); node->SetPivot(*(Point3*)&(boneDef.pivot)); node->Reference(obj); m_impInterface->AddNodeToScene(node); // 设置变换矩阵 Matrix3 tm; tm.IdentityMatrix(); tm.SetTrans(*(Point3*)&(boneDef.pivot)); node->SetTransform(0, tm); // 添加到组 INode* realINode = node->GetINode(); realINode->SetGroupHead(FALSE); realINode->SetGroupMember(TRUE); groupHeadNode->AttachChild(realINode); // 设置Bone父子关系 realINode->ShowBone(2); m_boneNodeList.push_back(realINode); if (boneDef.parent != -1) { INode* parentNode = m_boneNodeList[boneDef.parent]; parentNode->AttachChild(realINode); } realINode->EvalWorldState(0); } // 导入每根骨骼的关键桢数据 for (unsigned int i = 0; i < m_modelHeader->nBones; ++i) { ModelBoneDef& boneDef = boneData[i]; INode* realINode = m_boneNodeList[i]; Control* tmControl = realINode->GetTMController(); // Position if (boneDef.translation.nKeys) { // 设置动画控制器为线性控制器 Control* posControl = createPositionController(); tmControl->SetPositionController(posControl); unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.translation.ofsTimes); Point3* keyData = (Point3*)(m_m2FileData + boneDef.translation.ofsKeys); // 设置动画时间范围 bool animRangeChanged = false; Interval animRange = m_maxInterface->GetAnimRange(); for (unsigned int j = 0; j < boneDef.translation.nKeys; ++j) { if (timeData[j] < animRange.Start()) { animRange.SetStart(timeData[j]); animRangeChanged = true; } else if (timeData[j] > animRange.End()) { animRange.SetEnd(timeData[j]); animRangeChanged = true; } } if (animRangeChanged) m_maxInterface->SetAnimRange(animRange); // 设置动画关键桢数据 Control* xControl = posControl->GetXController(); IKeyControl* xKeyControl = GetKeyControlInterface(xControl); xKeyControl->SetNumKeys(boneDef.translation.nKeys); Control* yControl = posControl->GetYController(); IKeyControl* yKeyControl = GetKeyControlInterface(yControl); yKeyControl->SetNumKeys(boneDef.translation.nKeys); Control* zControl = posControl->GetZController(); IKeyControl* zKeyControl = GetKeyControlInterface(zControl); zKeyControl->SetNumKeys(boneDef.translation.nKeys); for (unsigned int j = 0; j < boneDef.translation.nKeys; ++j) { // X AnyKey bufX; ILinFloatKey* keyX = reinterpret_cast<ILinFloatKey*>((IKey*)bufX); keyX->time = timeData[j]; keyX->val = keyData[j].x; xKeyControl->AppendKey(keyX); // Y AnyKey bufY; ILinFloatKey* keyY = reinterpret_cast<ILinFloatKey*>((IKey*)bufY); keyY->time = timeData[j]; keyY->val = keyData[j].y; yKeyControl->AppendKey(keyY); // Z AnyKey bufZ; ILinFloatKey* keyZ = reinterpret_cast<ILinFloatKey*>((IKey*)bufZ); keyZ->time = timeData[j]; keyZ->val = keyData[j].z; zKeyControl->AppendKey(keyZ); } } /* // Rotation if (boneDef.rotation.nKeys) { Control* rotControl = createRotationController(); tmControl->SetRotationController(rotControl); unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.rotation.ofsTimes); Quat* keyData = (Quat*)(m_m2FileData + boneDef.rotation.ofsKeys); // 设置动画时间范围 bool animRangeChanged = false; Interval animRange = m_maxInterface->GetAnimRange(); for (unsigned int j = 0; j < boneDef.rotation.nKeys; ++j) { if (timeData[j] < animRange.Start()) { animRange.SetStart(timeData[j]); animRangeChanged = true; } else if (timeData[j] > animRange.End()) { animRange.SetEnd(timeData[j]); animRangeChanged = true; } } if (animRangeChanged) m_maxInterface->SetAnimRange(animRange); // 设置动画关键桢数据 IKeyControl* keyControl = GetKeyControlInterface(rotControl); keyControl->SetNumKeys(boneDef.rotation.nKeys); for (unsigned int j = 0; j < boneDef.rotation.nKeys; ++j) { AnyKey buf; ILinRotKey* key = reinterpret_cast<ILinRotKey*>((IKey*)buf); key->time = timeData[j]; key->val = keyData[j]; keyControl->AppendKey(key); } } */ // Scaling if (boneDef.scaling.nKeys) { Control* scaControl = createScaleController(); tmControl->SetScaleController(scaControl); unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.scaling.ofsTimes); Point3* keyData = (Point3*)(m_m2FileData + boneDef.scaling.ofsKeys); // 设置动画时间范围 bool animRangeChanged = false; Interval animRange = m_maxInterface->GetAnimRange(); for (unsigned int j = 0; j < boneDef.scaling.nKeys; ++j) { if (timeData[j] < animRange.Start()) { animRange.SetStart(timeData[j]); animRangeChanged = true; } else if (timeData[j] > animRange.End()) { animRange.SetEnd(timeData[j]); animRangeChanged = true; } } if (animRangeChanged) m_maxInterface->SetAnimRange(animRange); // 设置动画关键桢数据 IKeyControl* keyControl = GetKeyControlInterface(scaControl); keyControl->SetNumKeys(boneDef.scaling.nKeys); for (unsigned int j = 0; j < boneDef.scaling.nKeys; ++j) { AnyKey buf; ILinScaleKey* key = reinterpret_cast<ILinScaleKey*>((IKey*)buf); key->time = timeData[j]; key->val = ScaleValue(keyData[j]); keyControl->AppendKey(key); } } } }