/* Searches *db to construct **list, a list of mesh names associated with their chunk definition. */ void GetMeshNameList3ds(database3ds *db, /* The chunk database being searched */ namelist3ds **list /* The resulting namelist pairs, if *list is null, then a namelist structure will be allocated */ ) { chunk3ds *current=NULL, *nobj=NULL, *ntri; ulong3ds meshcount, i, j; if (db == NULL || list == NULL) SET_ERROR_RETURN(ERR_INVALID_ARG); /* Update the index to named objects if the list has changed recently */ UpdateNamedObjectList3ds(db); /* Get the number of meshes contained in the named object list */ meshcount = GetMeshCount3ds(db); /* Initilize the namelist array */ InitNameList3ds(list, meshcount); /* Scan through the list of named objects */ for (i = 0, j = 0; (i < db->objlist->count) && (j < meshcount); i++) { /* Search each named object for a mesh chunk */ FindChunk3ds(db->objlist->list[i].chunk, N_TRI_OBJECT, &ntri); /* If it is a mesh chunk */ if (ntri != NULL) { /* Copy the name into the list */ (*list)->list[j].name = strdup(db->objlist->list[i].name); j++; } } }
int Load3DS (const char * cpcName, C3DRender & rend) { file3ds *file= NULL; database3ds *db = NULL; CLEAR_ERROR; file = OpenFile3ds(cpcName, "r"); if (file == NULL) return __LINE__; rend.Clear (); rend.name = cpcName; InitDatabase3ds(&db); if (ftkerr3ds) return __LINE__; CreateDatabase3ds(file, db); if (ftkerr3ds) return __LINE__; rend.Protect (); // закрыть объект ренд ulong3ds nbrmat = GetMaterialCount3ds(db); if (ftkerr3ds) return __LINE__; rend.m_materials.resize (nbrmat+1); // 0 материал будет дефолтный! rend.m_materials[0].name = "_SMelm_def"; rend.m_materials[0].ambient.r = 0; rend.m_materials[0].ambient.g = 0; rend.m_materials[0].ambient.b = 0; rend.m_materials[0].ambient.a = 0; rend.m_materials[0].diffuse.r = 1; rend.m_materials[0].diffuse.g = 1; rend.m_materials[0].diffuse.b = 1; rend.m_materials[0].diffuse.a = 1; rend.m_materials[0].specular.r = 0; rend.m_materials[0].specular.g = 0; rend.m_materials[0].specular.b = 0; rend.m_materials[0].specular.a = 0; rend.m_materials[0].emission.r = 0; rend.m_materials[0].emission.g = 0; rend.m_materials[0].emission.b = 0; rend.m_materials[0].shininess = 0; rend.m_materials[0].shinstrength = 0; rend.m_materials[0].selfillumpct = 0; rend.m_materials[0].texture.map.is_loaded = false; rend.m_materials[0].texture.map.name = ""; rend.m_materials[0].reflect.map.is_loaded = false; rend.m_materials[0].reflect.map.name = ""; for (ulong3ds i = 0; i < nbrmat; ++i) { material3ds *mat=NULL; GetMaterialByIndex3ds(db, i, &mat); if (ftkerr3ds) return __LINE__; S3DMaterial &_mat = rend.m_materials[i+1]; _mat.name = mat->name; _mat.ambient.r = mat->ambient.r; _mat.ambient.g = mat->ambient.g; _mat.ambient.b = mat->ambient.b; _mat.ambient.a = 1; _mat.diffuse.r = mat->diffuse.r; _mat.diffuse.g = mat->diffuse.g; _mat.diffuse.b = mat->diffuse.b; _mat.diffuse.a = 1; _mat.specular.r = mat->specular.r * mat->shinstrength; _mat.specular.g = mat->specular.g * mat->shinstrength; _mat.specular.b = mat->specular.b * mat->shinstrength; _mat.specular.a = 1; _mat.shininess = mat->shininess; _mat.shinstrength = mat->shinstrength; _mat.selfillumpct = mat->selfillumpct; _mat.emission.r = 0.01f * _mat.selfillumpct; _mat.emission.g = 0.01f * _mat.selfillumpct; _mat.emission.b = 0.01f * _mat.selfillumpct; _mat.emission.a = 1; _mat.texture.map.is_loaded = false; _mat.texture.map.name = mat->texture.map.name; _mat.reflect.map.is_loaded = false; _mat.reflect.map.name = mat->reflect.map.name; ReleaseMaterial3ds(&mat); } ulong3ds nbrmesh = GetMeshCount3ds(db); if (ftkerr3ds) return __LINE__; rend.m_objects.resize (nbrmesh+1); // нужен объект типа ROOT нулевой rend.m_objects[0].name = ""; rend.m_objects[0].parent_name = "__NO__PARENT_MELMAN__"; rend.m_objects[0].parent_index = -1; for (ulong3ds i = 0; i < nbrmesh; ++i) { mesh3ds *mesh=NULL; GetMeshByIndex3ds(db, i, &mesh); if (ftkerr3ds) return __LINE__; S3DObject & _obj = rend.m_objects[i+1]; // скопировать имя _obj.name = mesh->name; _obj.parent_index = 0; // скопирвоать вершины _obj.vertexarray.resize (mesh->nvertices); for (unsigned int k = 0; k < mesh->nvertices; ++k) { _obj.vertexarray[k].Set (mesh->vertexarray[k].x, mesh->vertexarray[k].y, mesh->vertexarray[k].z); } // скопировать текстурные координаты _obj.textarray.resize (mesh->ntextverts); for (unsigned int k = 0; k < mesh->ntextverts; ++k) { _obj.textarray[k].u = mesh->textarray[k].u; _obj.textarray[k].v = mesh->textarray[k].v; } // задать локальную сист. координат. _obj.localCS.H.LoadIdentity (); C3DVectorF X1(mesh->locmatrix[0 * 3 + 0], mesh->locmatrix[0 * 3 + 1], mesh->locmatrix[0 * 3 + 2]); C3DVectorF X2(mesh->locmatrix[1 * 3 + 0], mesh->locmatrix[1 * 3 + 1], mesh->locmatrix[1 * 3 + 2]); C3DVectorF X3(mesh->locmatrix[2 * 3 + 0], mesh->locmatrix[2 * 3 + 1], mesh->locmatrix[2 * 3 + 2]); C3DVectorF O (mesh->locmatrix[3 * 3 + 0], mesh->locmatrix[3 * 3 + 1], mesh->locmatrix[3 * 3 + 2]); _obj.localCS.H_from_zero.LoadInverseTransform (X1, X2, X3, O); // загрузить матрицу трансформации из 0! _obj.localCS.H_from_zero.Transpose (); // транспонировать для OpenGL - нужно ли??? _obj.localCS.H_to_zero = _obj.localCS.H_from_zero.Invert (); // матрица возврата в 0 _obj.localCS.pivot.Set (0,0,0); // // распределить меши if (mesh->nmats > 0) { _obj.meshes.resize (mesh->nmats);// количество подмешей. for (unsigned int k = 0; k < mesh->nmats; ++k) { const objmat3ds & omat = mesh->matarray[k]; _obj.meshes[k].matname = omat.name; // скопировать имя и найти локальный индекс материала используемый подмешем. _obj.meshes[k].MatIndex = rend.GetMaterialIndex (omat.name); // если не будет найдено имя материала то будем использовать 0 как дефолтный. // скопировать фейсы подмеша _obj.meshes[k].facearray.resize (omat.nfaces); for (unsigned int j = 0; j < omat.nfaces; ++j) { _obj.meshes[k].facearray[j].V1 = mesh->facearray[omat.faceindex[j]].v1; _obj.meshes[k].facearray[j].V2 = mesh->facearray[omat.faceindex[j]].v2; _obj.meshes[k].facearray[j].V3 = mesh->facearray[omat.faceindex[j]].v3; } } } else { // так бывает если нет ни одного материала и нет разбивки на подмеши, нужно все засунуть в 1 меш. _obj.meshes.resize (1);// количество подмешей. _obj.meshes[0].matname = "_SMelm_def"; // дефолтный материал _obj.meshes[0].MatIndex = 0; // // скопировать фейсы подмеша _obj.meshes[0].facearray.resize (mesh->nfaces); for (unsigned int j = 0; j < mesh->nfaces; ++j) { _obj.meshes[0].facearray[j].V1 = mesh->facearray[j].v1; _obj.meshes[0].facearray[j].V2 = mesh->facearray[j].v2; _obj.meshes[0].facearray[j].V3 = mesh->facearray[j].v3; } } RelMeshObj3ds(&mesh); } ulong3ds nbrobj = GetObjectNodeCount3ds(db); if (ftkerr3ds) return __LINE__; for (ulong3ds i = 0; i < nbrobj; ++i) { kfmesh3ds *omo=NULL; GetObjectMotionByIndex3ds (db, i, &omo); if (ftkerr3ds) return __LINE__; std::string oname = omo->name; if (oname == "$$$DUMMY") // блядский пустой узел { // его нужно внести в список объектов S3DObject dymmy; dymmy.name = oname + "." + omo->instance; dymmy.localCS.pivot.Set (omo->pivot.x, omo->pivot.y, omo->pivot.z); dymmy.localCS.H.LoadIdentity (); dymmy.localCS.H_from_zero.LoadIdentity (); dymmy.localCS.H_to_zero.LoadIdentity (); dymmy.parent_name = omo->parent; dymmy.parent_index = rend.GetObjectIndex (omo->parent); rend.m_objects.push_back (dymmy); } else { int oi = rend.GetObjectIndex (omo->name); if (oi != -1) // такого быть не должно иначе чушь! { rend.m_objects[oi].parent_name = omo->parent; rend.m_objects[oi].parent_index = rend.GetObjectIndex (omo->parent); rend.m_objects[oi].localCS.pivot.Set (omo->pivot.x, omo->pivot.y, omo->pivot.z); } } ReleaseObjectMotion3ds (&omo); } ReleaseDatabase3ds(&db); CloseFile3ds(file); CloseAllFiles3ds (); // рассчитать нормали для всех объектов rend.CalcNormals (); rend.LoadTextures (); // структура считана и заполнена. // теперь нужно дерево иерархии заполнить как-нибудь.... rend.m_tree.obj_index = 0; FindAllRefsToMe (rend.m_tree, rend); rend.UnProtect (); return 0; }