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* NifImporter::CreateImportNode(const char *name, Object *obj, INode* parent) { #if USE_IMPORTNODE ImpNode* impNode = i->CreateNode(); impNode->Reference(obj); if (INode *n = impNode->GetINode()) { n->SetName(const_cast<TCHAR*>(name)); n->SetObjectRef(obj); i->AddNodeToScene(impNode); this->RegisterNode(name, n); if (parent) { parent->AttachChild(impNode->GetINode()); ASSERT(parent == n->GetParentNode()); } } return impNode->GetINode(); #else if ( INode* n = gi->CreateObjectNode(obj) ) { n->SetName(const_cast<TCHAR*>(name)); this->RegisterNode(name, n); if (parent) { parent->AttachChild(n); ASSERT(parent == n->GetParentNode()); } return n; } return NULL; #endif }
INode* M2Importer::createGroupHeaderNode() { DummyObject* obj = (DummyObject*)CreateInstance(HELPER_CLASS_ID, Class_ID(DUMMY_CLASS_ID, 0)); ImpNode* node = m_impInterface->CreateNode(); node->Reference(obj); m_impInterface->AddNodeToScene(node); return node->GetINode(); }
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(); }
bool SceneGraphCreator::importInstances( const COLLADAFW::PointerArray<Instance>& instanceArray, ImpNode* parentImportNode ) { for ( size_t i = 0, count = instanceArray.getCount(); i < count; ++i) { Instance* instance = instanceArray[i]; ImpNode* newImportNode = getMaxImportInterface()->CreateNode(); INode* newNode = newImportNode->GetINode(); const COLLADAFW::UniqueId& uniqueId = instance->getInstanciatedObjectId(); Object* object = getObjectByUniqueId(uniqueId); if ( object ) { newImportNode->Reference(object); } else { newImportNode->Reference( getDummyObject() ); } const COLLADAFW::UniqueId& instanceUniqueId = instance->getInstanciatedObjectId(); // Store mapping between unique ids and nodes referencing the corresponding object. // Used to clone nodes addObjectINodeUniqueIdPair(newNode, instanceUniqueId); // Used to resolve instancing of objects addUniqueIdObjectINodePair(instanceUniqueId, newNode); INode* parentNode = parentImportNode->GetINode(); parentNode->AttachChild(newNode, FALSE); // post process the creation if ( postProcess ) (this->*postProcess)(newNode, instance); } return true; }
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; }
//------------------------------ ImpNode* SceneGraphCreator::importNode( const COLLADAFW::Node* node, INode* parentINode ) { bool singleInstance = (node->getInstanceGeometries().getCount() + node->getInstanceControllers().getCount() + node->getInstanceCameras().getCount() + node->getInstanceLights().getCount() ) == 1; ImpNode* newImportNode = 0; const COLLADAFW::UniqueId& nodeUniqueId = node->getUniqueId(); if ( !singleInstance ) { newImportNode = getMaxImportInterface()->CreateNode(); setNodeProperties(node, newImportNode); getMaxImportInterface()->AddNodeToScene(newImportNode); RefResult res = newImportNode->Reference(getDummyObject()); if ( node->getType() == COLLADAFW::Node::JOINT ) { newImportNode->GetINode()->ShowBone(1); } importInstanceGeometries(node->getInstanceGeometries(), newImportNode); importInstanceControllers(node->getInstanceControllers(), newImportNode); importInstanceCameras(node->getInstanceCameras(), newImportNode); importInstanceLights(node->getInstanceLights(), newImportNode); } else { newImportNode = importInstanceGeometry( node, parentINode ); if ( !newImportNode ) newImportNode = importInstanceController( node, parentINode ); if ( !newImportNode ) newImportNode = importInstanceCamera( node, parentINode ); if ( !newImportNode ) newImportNode = importInstanceLight( node, parentINode ); assert(newImportNode); } INode* childNode = newImportNode->GetINode(); importNodes(node->getChildNodes(), childNode); // Append all nodes that are referenced by this node. importInstanceNodes(node->getInstanceNodes(), newImportNode); /** Store the unique id of the created node, to resolve references, when ever necessary.*/ addUniqueIdINodePair( nodeUniqueId, newImportNode->GetINode()); parentINode->AttachChild(childNode, FALSE); #if 0 /* if there are nodes that reference the just created node, clone this node and append it to the referencing node.*/ ImpNode* referencingImpNode = 0; while ( referencingImpNode = getReferencingImpNodesByUniqueId(nodeUniqueId) ) { removeUniqueIdReferencingImpNodePair( nodeUniqueId, referencingImpNode); recursivelyCloneINode( referencingImpNode, newImportNode->GetINode() ); } #endif return newImportNode; }
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; }
void WMOGroupImpl::buildMaxData() { // Group Header Node INode* groupHeadNode = createGroupHeaderNode(); groupHeadNode->SetGroupHead(TRUE); groupHeadNode->SetGroupMember(FALSE); // Geoset // 一个Render Batch构造一个Node, 并且加入到组中 for (int i = 0; i < m_batchCount; ++i) { WMORenderBatch& renderBatch = m_batchData[i]; m_wmoImporter->m_logStream << "Model Geoset " << i << " Vertex Info: " << renderBatch.vertexStart << " -- " << renderBatch.vertexEnd << endl; m_wmoImporter->m_logStream << "Model Geoset " << i << " Index Info: " << renderBatch.indexStart << " -- " << renderBatch.indexCount << endl; // Triangle Mesh Object // 基本的三角形模型对象 TriObject* triObject = CreateNewTriObject(); // 创建Node, 并且设为Group Header Node的子节点 ImpNode* tmpImpNode = m_wmoImporter->m_impInterface->CreateNode(); tmpImpNode->Reference(triObject); m_wmoImporter->m_impInterface->AddNodeToScene(tmpImpNode); INode* realINode = tmpImpNode->GetINode(); realINode->SetGroupHead(FALSE); realINode->SetGroupMember(TRUE); groupHeadNode->AttachChild(realINode); m_geosetNodeList.push_back(realINode); TCHAR nodeName[256]; sprintf(nodeName, "%s_part_%03d", m_groupName.c_str(), i); realINode->SetName(nodeName); // mesh unsigned short vertexCount = renderBatch.vertexEnd - renderBatch.vertexStart + 1; unsigned int trigangleCount = renderBatch.indexCount / 3; Mesh& mesh = triObject->GetMesh(); mesh.setNumVerts(vertexCount); mesh.setNumTVerts(vertexCount, TRUE); mesh.setNumFaces(trigangleCount); mesh.setNumTVFaces(trigangleCount); // 顶点坐标和UV for (int i = 0; i < vertexCount; ++i) { mesh.verts[i] = *(Point3*)(&(m_vertexData[renderBatch.vertexStart + i])); // UV坐标反转 mesh.tVerts[i].x = m_textureCoords[renderBatch.vertexStart + i].x; mesh.tVerts[i].y = 1.0f - m_textureCoords[renderBatch.vertexStart + i].y; } // 三角形 for (unsigned int i = 0; i < trigangleCount; ++i) { Face& face = mesh.faces[i]; int index1 = m_indexData[renderBatch.indexStart + i*3] - renderBatch.vertexStart; int index2 = m_indexData[renderBatch.indexStart + i*3+1] - renderBatch.vertexStart; int index3 = m_indexData[renderBatch.indexStart + i*3+2] - renderBatch.vertexStart; face.setVerts(index1, index2, index3); face.Show(); face.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS); TVFace& tface = mesh.tvFace[i]; tface.setTVerts(index1, index2, index3); } // 法线 mesh.SpecifyNormals(); MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (specNorms) { specNorms->ClearAndFree(); specNorms->SetNumFaces(trigangleCount); specNorms->SetNumNormals(vertexCount); Point3* norms = specNorms->GetNormalArray(); for (int i = 0; i < vertexCount; ++i) { norms[i] = *(Point3*)(&m_normalData[renderBatch.vertexStart + i]); } MeshNormalFace* pFaces = specNorms->GetFaceArray(); for (unsigned int i = 0; i < trigangleCount; ++i) { int index1 = m_indexData[renderBatch.indexStart + i*3] - renderBatch.vertexStart; int index2 = m_indexData[renderBatch.indexStart + i*3+1] - renderBatch.vertexStart; int index3 = m_indexData[renderBatch.indexStart + i*3+2] - renderBatch.vertexStart; pFaces[i].SpecifyNormalID(0, index1); pFaces[i].SpecifyNormalID(1, index2); pFaces[i].SpecifyNormalID(2, index3); } specNorms->SetAllExplicit(true); specNorms->CheckNormals(); } // 删除重复的和无效的面 mesh.RemoveDegenerateFaces(); mesh.RemoveIllegalFaces(); realINode->SetMtl(m_wmoImporter->m_materialList[renderBatch.texture]); //realINode->BackCull(FALSE); // 取消背面裁减 不是所有的Node都要取消背面裁减 realINode->EvalWorldState(0); } }
// 1. 加载模型顶点数据 void M2Importer::importGeomObject() { // 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); groupHeadNode->SetName(modelName); m_logStream << "ModelName: " << modelName << endl; } else groupHeadNode->SetName("GeomGroup"); // Geoset // 一个Geoset构造一个Node, 并且加入到组中 unsigned short* verDataIndex = (unsigned short*)(m_m2FileData + m_modelView->ofsIndex); unsigned short* triData = (unsigned short*)(m_m2FileData + m_modelView->ofsTris); m_geosetNodeList.reserve(m_modelView->nSub); m_materialList.reserve(m_modelView->nSub); for (unsigned int i = 0; i < m_modelView->nSub; ++i) m_materialList.push_back(0); for (unsigned int i = 0; i < m_modelView->nSub; ++i) { ModelGeoset& geosetData = m_modelGeoset[i]; // Triangle Mesh Object // 基本的三角形模型对象 TriObject* triObject = CreateNewTriObject(); // 创建Node, 并且设为Group Header Node的子节点 ImpNode* tmpImpNode = m_impInterface->CreateNode(); tmpImpNode->Reference(triObject); //tmpImpNode->SetPivot(*(Point3*)&(geosetData.v)); m_impInterface->AddNodeToScene(tmpImpNode); INode* realINode = tmpImpNode->GetINode(); realINode->SetGroupHead(FALSE); realINode->SetGroupMember(TRUE); groupHeadNode->AttachChild(realINode); m_geosetNodeList.push_back(realINode); TCHAR nodeName[256]; sprintf(nodeName, "GeosetPart_%d", i); realINode->SetName(nodeName); // mesh Mesh& mesh = triObject->GetMesh(); mesh.setNumVerts(geosetData.vcount); mesh.setNumTVerts(geosetData.vcount, TRUE); unsigned int triangeCount = geosetData.icount / 3; mesh.setNumFaces(triangeCount); mesh.setNumTVFaces(triangeCount); m_logStream << "Model Geoset " << i << " Vertex Count: " << geosetData.vcount << endl; m_logStream << "Model Geoset " << i << " Index Count: " << triangeCount << endl; // 顶点坐标和UV for (unsigned int i = 0; i < geosetData.vcount; ++i) { ModelVertex& vertexData = m_globalVertices[ verDataIndex[geosetData.vstart + i] ]; mesh.verts[i] = *(Point3*)(&vertexData.pos); // UV坐标反转 mesh.tVerts[i].x = vertexData.texcoords.x; mesh.tVerts[i].y = 1.0f - vertexData.texcoords.y; } // 三角形 for (unsigned int i = 0; i < triangeCount; ++i) { Face& face = mesh.faces[i]; face.setVerts(triData[geosetData.istart + i*3] - m_indexCount, triData[geosetData.istart + i*3+1] - m_indexCount, triData[geosetData.istart + i*3+2] - m_indexCount); face.Show(); face.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS); TVFace& tface = mesh.tvFace[i]; tface.setTVerts(triData[geosetData.istart + i*3] - m_indexCount, triData[geosetData.istart + i*3+1] - m_indexCount, triData[geosetData.istart + i*3+2] - m_indexCount); } // 法线 mesh.SpecifyNormals(); MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (specNorms) { specNorms->ClearAndFree(); specNorms->SetNumFaces(triangeCount); specNorms->SetNumNormals(geosetData.vcount); Point3* norms = specNorms->GetNormalArray(); for (unsigned int i = 0; i < geosetData.vcount; ++i) { ModelVertex& vertexData = m_globalVertices[ verDataIndex[geosetData.vstart + i] ]; norms[i] = *(Point3*)(&vertexData.normal); } MeshNormalFace* pFaces = specNorms->GetFaceArray(); for (unsigned int i = 0; i < triangeCount; ++i) { pFaces[i].SpecifyNormalID(0, triData[geosetData.istart + i*3] - m_indexCount); pFaces[i].SpecifyNormalID(1, triData[geosetData.istart + i*3+1] - m_indexCount); pFaces[i].SpecifyNormalID(2, triData[geosetData.istart + i*3+2] - m_indexCount); } specNorms->SetAllExplicit(true); specNorms->CheckNormals(); } // 删除重复的和无效的面 mesh.RemoveDegenerateFaces(); mesh.RemoveIllegalFaces(); //realINode->BackCull(FALSE); // 取消背面裁减 双面绘制与取消背面裁减一起设置 realINode->EvalWorldState(0); // 索引值修正 m_indexCount += geosetData.vcount; } // 加载材质 unsigned short* texLookupData = (unsigned short*)(m_m2FileData + m_modelHeader->ofsTexLookup); ModelTextureDef* texUnitDefData = (ModelTextureDef*)(m_m2FileData + m_modelHeader->ofsTextures); ModelTexUnit* texUnitData = (ModelTexUnit*)(m_m2FileData + m_modelView->ofsTex); for (unsigned int i = 0; i < m_modelView->nTex; ++i) { ModelTexUnit& texUnit = texUnitData[i]; unsigned short textureID = texLookupData[texUnit.textureid]; ModelTextureDef& texDef = texUnitDefData[textureID]; string textureName; if (texDef.type == 0) textureName = (LPCSTR)(m_m2FileData + texDef.nameOfs); else textureName = getReplacableTexture(texDef.type); StdMat2* material = m_materialList[texUnit.op]; if (!material) material = createMaterial(); // 根据混合属性决定加在第几层 material->SetSubTexmap(ID_DI, createTexture(textureName.c_str())); material->EnableMap(ID_DI, TRUE); //material->SetTwoSided(TRUE); // 双面 设置了此标志的才打开 m_maxInterface->GetMaterialLibrary().Add(material); m_geosetNodeList[texUnit.op]->SetMtl(material); } m_maxInterface->RedrawViews(m_maxInterface->GetTime()); }
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 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; }
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; }
// 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); } } } }