void L3DS::ReadFaceList(const LChunk &chunk, LMesh &mesh) { // variables unsigned short count, t; uint i; LTri tri; LChunk ch; char str[20]; //uint mat; // consistency checks if (chunk.id != TRI_FACELIST) { ErrorMsg("L3DS::ReadFaceList - internal error: wrong chunk passed as parameter"); return; } GotoChunk(chunk); tri.smoothingGroups = 1; // read the number of faces count = ReadShort(); mesh.SetTriangleArraySize(count); for (i=0; i<count; i++) { tri.a = ReadShort(); tri.b = ReadShort(); tri.c = ReadShort(); ReadShort(); mesh.SetTri(tri, i); } // now read the optional chunks ch = ReadChunk(); int mat_id; while (ch.end <= chunk.end) { switch (ch.id) { case TRI_MAT_GROUP: ReadASCIIZ(str, 20); mat_id=0; if (FindMaterial(str)!=NULL) mat_id = FindMaterial(str)->GetID(); mesh.AddMaterial(mat_id); count = ReadShort(); for (i=0; i<count; i++) { t = ReadShort(); mesh.GetTri(t).materialId = mat_id; } break; case TRI_SMOOTH_GROUP: for (i=0; i<mesh.GetTriangleCount(); i++) mesh.GetTri(i).smoothingGroups = (ulong) ReadInt(); break; } SkipChunk(ch); ch = ReadChunk(); } }
/************* * DESCRIPTION: read a material-chunk * INPUT: pointer to chunk * OUTPUT: - *************/ static void ParsePropMat(HANDLER_DATA *data, CHUNK *mainchunk) { CHUNK chunk; SURFACE *surf; float perc; COLOR color, diffuse; char buf[80]; surf = data->link->SurfaceAdd(data->rc); if (!surf) { data->err = ERR_MEM; return; } do { BeginChunk(data, &chunk); switch (chunk.id) { case ID_PROPNAME: ReadASCIIZ(data, buf); if (!data->link->SurfaceName(data->rc, surf,buf)) { data->err = ERR_MEM; return; } break; case ID_AMBIENT: ParseColor(data, &color); data->link->SurfaceAmbient(data->rc, surf,color.r,color.g,color.b); break; case ID_DIFFUSE: ParseColor(data, &diffuse); data->link->SurfaceDiffuse(data->rc, surf,diffuse.r,diffuse.g,diffuse.b); break; case ID_SPECULAR: ParseColor(data, &color); data->link->SurfaceSpecular(data->rc, surf,color.r,color.g,color.b); break; case ID_SHININESS: perc = ParsePercentage(data); data->link->SurfaceRefPhong(data->rc, surf,perc*100.f); break; case ID_TRANSPARENCY: perc = ParsePercentage(data); data->link->SurfaceTranspar(data->rc, surf,perc*diffuse.r,perc*diffuse.g,perc*diffuse.b); break; } EndChunk(data, &chunk); } while (INCHUNK); }
void L3DS::ReadMap(const LChunk &chunk, LMap& map) { LChunk child; char str[20]; GotoChunk(chunk); child = ReadChunk(); while (child.end <= chunk.end) { switch (child.id) { case INT_PERCENTAGE: map.strength = ReadPercentage(child); break; case MAT_MAPNAME: ReadASCIIZ(str, 20); strcpy(map.mapName, str); break; case MAT_MAP_TILING: map.tiling = ReadShort(); break; case MAT_MAP_USCALE: map.uScale = ReadFloat(); break; case MAT_MAP_VSCALE: map.vScale = ReadFloat(); break; case MAT_MAP_UOFFSET: map.uOffset = ReadFloat(); break; case MAT_MAP_VOFFSET: map.vOffset = ReadFloat(); break; case MAT_MAP_ANG: map.angle = ReadFloat(); break; } SkipChunk(child); child = ReadChunk(); } }
void L3DS::ReadKeyframeData(const LChunk &parent) { uint frames = 0; LChunk node_hdr; node_hdr.id = NODE_HDR; char str[20]; LMesh *mesh; GotoChunk(parent); if (!FindChunk(node_hdr, parent)) return; GotoChunk(node_hdr); ReadASCIIZ(str, 19); mesh = FindMesh(str); if (mesh == 0) return; GotoChunk(parent); // read the pivot //LVector3 pivot = zero3; LChunk pivotchunk; pivotchunk.id = PIVOT; if (FindChunk(pivotchunk, parent)) { GotoChunk(pivotchunk); /*pivot.x =*/ ReadFloat(); /*pivot.y =*/ ReadFloat(); /*pivot.z =*/ ReadFloat(); } GotoChunk(parent); // read frame 0 from the position track //LVector3 pos = zero3; frames = 0; LChunk poschunk; poschunk.id = POS_TRACK_TAG; if (FindChunk(poschunk, parent)) { GotoChunk(poschunk); // read the trackheader structure ReadShort(); ReadInt(); ReadInt(); frames = ReadInt(); if (frames > 0) { ReadKeyheader(); /*pos.x =*/ ReadFloat(); /*pos.y =*/ ReadFloat(); /*pos.z =*/ ReadFloat(); } } GotoChunk(parent); // now read the rotation track //LVector4 rot = zero4; LChunk rotchunk; rotchunk.id = ROT_TRACK_TAG; frames = 0; if (FindChunk(rotchunk, parent)) { GotoChunk(rotchunk); // read the trackheader structure ReadShort(); ReadInt(); ReadInt(); frames = ReadInt(); if (frames > 0) { ReadKeyheader(); /*rot.x =*/ ReadFloat(); /*rot.y =*/ ReadFloat(); /*rot.z =*/ ReadFloat(); /*rot.w =*/ ReadFloat(); } } GotoChunk(parent); // now read the scaling chunk //LVector3 scale; //scale.x = 1; //scale.y = 1; //scale.z = 1; LChunk scalechunk; scalechunk.id = SCL_TRACK_TAG; frames = 0; if (FindChunk(scalechunk, parent)) { GotoChunk(scalechunk); // read the trackheader structure ReadShort(); ReadInt(); ReadInt(); frames = ReadInt(); if (frames > 0) { ReadKeyheader(); /*scale.x =*/ ReadFloat(); /*scale.y =*/ ReadFloat(); /*scale.z =*/ ReadFloat(); } } GotoChunk(parent); }
void L3DS::ReadMaterial(const LChunk &parent) { // variables LChunk chunk; LChunk child; char str[30]; LMaterial mat; short sh; GotoChunk(parent); chunk = ReadChunk(); while (chunk.end <= parent.end) { switch (chunk.id) { case MAT_NAME: ReadASCIIZ(str, 30); mat.SetName(str); break; case MAT_AMBIENT: child = ReadChunk(); mat.SetAmbientColor(ReadColor(child)); break; case MAT_DIFFUSE: child = ReadChunk(); mat.SetDiffuseColor(ReadColor(child)); break; case MAT_SPECULAR: child = ReadChunk(); mat.SetSpecularColor(ReadColor(child)); break; case MAT_SHININESS: child = ReadChunk(); mat.SetShininess(ReadPercentage(child)); break; case MAT_TRANSPARENCY: child = ReadChunk(); mat.SetTransparency(ReadPercentage(child)); break; case MAT_SHADING: sh = ReadShort(); switch (sh) { case 0: mat.SetShadingType(sWireframe); break; case 1: mat.SetShadingType(sFlat); break; case 2: mat.SetShadingType(sGouraud); break; case 3: mat.SetShadingType(sPhong); break; case 4: mat.SetShadingType(sMetal); break; } break; case MAT_WIRE: mat.SetShadingType(sWireframe); break; case MAT_TEXMAP: ReadMap(chunk, mat.GetTextureMap1()); break; case MAT_TEX2MAP: ReadMap(chunk, mat.GetTextureMap2()); break; case MAT_OPACMAP: ReadMap(chunk, mat.GetOpacityMap()); break; case MAT_BUMPMAP: ReadMap(chunk, mat.GetBumpMap()); break; case MAT_SPECMAP: ReadMap(chunk, mat.GetSpecularMap()); break; case MAT_REFLMAP: // AMZ not really a bugfix but it seems to work! #if 1 ReadMap(chunk, mat.GetReflectionMap()); #else child = ReadChunk(); mat.GetReflectionMap().strength = ReadPercentage(child); SkipChunk(child); child = ReadChunk(); if (child.id != MAT_MAPNAME) { fprintf(stderr, "L3DS::ReadMaterial - error, expected chunk not found"); return; } ReadASCIIZ(str, 30); if (strcmp(str, "") == 0) strcpy(mat.GetReflectionMap().mapName, "auto"); #endif break; } SkipChunk(chunk); chunk = ReadChunk(); } m_materials.push_back(mat); m_materials[m_materials.size()-1].SetID(uint(m_materials.size())-1); }
bool L3DS::Read3DS() { LChunk mainchunk; LChunk edit; edit.id = EDIT3DS; mainchunk = ReadChunk(); if (mainchunk.id != MAIN3DS) { fprintf(stderr, "L3DS::Read3DS - wrong file format"); return false; } if (!FindChunk(edit, mainchunk)) return false; LChunk obj; LChunk ml; GotoChunk(edit); obj.id = MAT_ENTRY; while (FindChunk(obj, edit)) { ReadMaterial(obj); SkipChunk(obj); } GotoChunk(edit); obj.id = EDIT_OBJECT; { while (FindChunk(obj, edit)) { ReadASCIIZ(m_objName, 99); ml = ReadChunk(); if (ml.id == OBJ_TRIMESH) ReadMesh(ml); else if (ml.id == OBJ_LIGHT) ReadLight(ml); else if (ml.id == OBJ_CAMERA) ReadCamera(ml); SkipChunk(obj); } } // read the keyframer data here to find out correct object orientation LChunk keyframer; keyframer.id = KFDATA; LChunk objtrack; objtrack.id = OBJECT_NODE_TAG; GotoChunk(mainchunk); if (FindChunk(keyframer, mainchunk)) { // keyframer chunk is present GotoChunk(keyframer); while (FindChunk(objtrack, keyframer)) { ReadKeyframeData(objtrack); SkipChunk(objtrack); } } for (uint i=0; i<m_meshes.size(); i++) m_meshes[i].Optimize(m_optLevel); m_pos = 0; strcpy(m_objName, ""); return true; }
/************* * DESCRIPTION: - * INPUT: pointer to chunk * OUTPUT: - *************/ static void ParseNamedObject(HANDLER_DATA *data, CHUNK *mainchunk) { CHUNK chunk; TRIANGLE *triangle; TRILIST *ph1,*ph2; float angle; UWORD p1, p2, p3; UWORD *edges; int i, h; ReadASCIIZ(data, data->ObjName); do { BeginChunk(data, &chunk); switch (chunk.id) { case ID_TRIANGLE: ParseTriObject(data, &chunk); break; } EndChunk(data, &chunk); } while (INCHUNK); if (data->TriList && (data->link->type == LINK_RENDERER)) { // go through all vertices and calculate normals (only for renderer) for (i = 0; i < data->pointcount; i++) { data->VertNorms[i].x = data->VertNorms[i].y = data->VertNorms[i].z = 0.f; ph1 = data->TriList[i]; while (ph1) { for (ph2 = ph1->next; ph2 != NULL; ph2 = ph2->next) { if (!ph1->flag || !ph2->flag) { // test angle between two triangles angle = VecAngle(data->TriNorms[ph1->tri], data->TriNorms[ph2->tri]); // if (angle < 2*PI && angle > /*cos_*/smooth_angle) if (angle >0 && angle < /*cos_*/data->smooth_angle) { if (!ph1->flag) { VecAdd(&data->VertNorms[i], &data->TriNorms[ph1->tri], &data->VertNorms[i]); ph1->flag = TRUE; data->TriSmooth[ph1->tri] = TRUE; } if (!ph2->flag) { VecAdd(&data->VertNorms[i], &data->TriNorms[ph2->tri], &data->VertNorms[i]); ph2->flag = TRUE; data->TriSmooth[ph2->tri] = TRUE; } } } } ph2 = ph1; ph1 = ph1->next; delete ph2; } VecNormalize(&data->VertNorms[i]); } } if (data->face) { data->link->ObjectBegin(data->rc); data->defaultsurface = data->link->SurfaceAdd(data->rc); if (!data->defaultsurface) { data->err = ERR_MEM; return; } data->link->SurfaceName(data->rc, data->defaultsurface, "default"); data->link->SurfaceDiffuse(data->rc, data->defaultsurface, 0.9f, 0.9f, 0.9f); data->link->SurfaceAmbient(data->rc, data->defaultsurface, 0.1f, 0.1f, 0.1f); data->link->SurfaceRefPhong(data->rc, data->defaultsurface, 49.f); triangle = data->link->TriangleAdd(data->rc, data->facecount,data->defaultsurface,data->mainactor); if (!triangle) { data->err = ERR_MEM; return; } if (data->link->type == LINK_SCENARIO) { // modeler needs points,edges and faces seperate if (data->link->TriangleAddPoints(data->rc, data->pointcount,data->points) == -1) { data->err = ERR_MEM; return; } edges = new UWORD[data->facecount*6]; if (!edges) { data->err = ERR_MEM; return; } for (i = 0; i < data->facecount; i++) { h = i*6; edges[h++] = data->face[i].p1; edges[h++] = data->face[i].p2; edges[h++] = data->face[i].p2; edges[h++] = data->face[i].p3; edges[h++] = data->face[i].p3; edges[h++] = data->face[i].p1; } if (data->link->TriangleAddEdges(data->rc, data->facecount*3,edges) == -1) { delete edges; data->err = ERR_MEM; return; } delete edges; } for (i = 0; i < data->facecount; i++) { p1 = data->face[i].p1; p2 = data->face[i].p3; p3 = data->face[i].p2; if(data->replacesurface) data->link->TriangleSurface(data->rc, triangle, data->replacesurface); else { if(!data->material[i]) data->link->TriangleSurface(data->rc, triangle, data->defaultsurface); else data->link->TriangleSurface(data->rc, triangle, data->material[i]); } if (data->link->type == LINK_SCENARIO) { // modeler needs edges data->link->TriangleSetEdges(data->rc, triangle,i*3,i*3+1,i*3+2); } else { // raystorm renderer needs triangles and normals data->link->TrianglePoints(data->rc, triangle,&data->points[p1],&data->points[p2],&data->points[p3]); if (!VecZero(data->TriNorms[i])) { // generate smooth triangle when smooth flag is set if (data->TriSmooth[i]) { data->link->TriangleVNorm(data->rc, triangle, VecZero(data->VertNorms[p1]) ? &data->TriNorms[i] : &data->VertNorms[p1], VecZero(data->VertNorms[p2]) ? &data->TriNorms[i] : &data->VertNorms[p2], VecZero(data->VertNorms[p3]) ? &data->TriNorms[i] : &data->VertNorms[p3]); } } if(data->mapping) { data->link->TriangleUV(data->rc, triangle, &data->mapping[p1], &data->mapping[p2], &data->mapping[p3]); } } // next triangle triangle = data->link->TriangleGetNext(data->rc, triangle); } data->link->ObjectEnd(data->rc); } CleanupMesh(data); }
/************* * DESCRIPTION: read faces of object * INPUT: pointer to chunk * OUTPUT: - *************/ static void ParseFaces(HANDLER_DATA *data, CHUNK *mainchunk) { CHUNK chunk; UWORD i, matcount, index, p1, p2, p3; VECTOR e1, e2; SURFACE *s; TRILIST *hp; char buf[80]; ReadWord(data, (WORD *)&data->facecount, 1); // read number of faces if (data->facecount == 0) return; data->face = new FACE3DS[data->facecount]; if (!data->face) { data->err = ERR_MEM; return; } if (!data->replacesurface) { data->material = (SURFACE **)malloc(sizeof(SURFACE *)*data->facecount); if (!data->material) { data->err = ERR_MEM; return; } } ReadWord(data, (WORD *)data->face, 4*data->facecount); // read faces if (data->link->type == LINK_RENDERER) { // do it for renderer only data->VertNorms = new VECTOR[data->pointcount]; if (!data->VertNorms) { data->err = ERR_MEM; return; } data->TriNorms = new VECTOR[data->facecount]; if (!data->TriNorms) { data->err = ERR_MEM; return; } memset(data->VertNorms, 0, sizeof(VECTOR)*data->pointcount); // Init normals data->TriSmooth = new UBYTE[data->facecount]; if (!data->TriSmooth) { data->err = ERR_MEM; return; } for (i = 0; i < data->facecount; i++) { if (data->replacesurface) data->material[i] = data->replacesurface; else data->material[i] = NULL; data->TriSmooth[i] = FALSE; // get three points for the triangle p1 = data->face[i].p1; p2 = data->face[i].p3; p3 = data->face[i].p2; hp = new TRILIST; if (!hp) { data->err = ERR_MEM; return; } hp->next = data->TriList[p1]; hp->tri = i; hp->flag = FALSE; data->TriList[p1] = hp; hp = new TRILIST; if (!hp) { data->err = ERR_MEM; return; } hp->next = data->TriList[p2]; hp->tri = i; hp->flag = FALSE; data->TriList[p2] = hp; hp = new TRILIST; if (!hp) { data->err = ERR_MEM; return; } hp->next = data->TriList[p3]; hp->tri = i; hp->flag = FALSE; data->TriList[p3] = hp; // calculate normal of triangle VecSub(&data->points[p3], &data->points[p1], &e1); VecSub(&data->points[p2], &data->points[p1], &e2); VecNormCross(&e1, &e2, &data->TriNorms[i]); } } do { BeginChunk(data, &chunk); switch (chunk.id) { case ID_MSHMATGROUP: if (!data->replacesurface) { ReadASCIIZ(data, buf); s = data->link->SurfaceGetByName(data->rc, buf); ReadWord(data, (WORD*)&matcount, 1); for (i = 0; i < matcount; i++) { ReadWord(data, (WORD*)&index, 1); data->material[index] = s; } } break; case ID_SMOOTHGROUP: // no info about this group break; } EndChunk(data, &chunk); } while (INCHUNK); }