void C3DOParser::GetPrimitives(S3DOPiece* obj, int pos, int num, int excludePrim, const std::vector<unsigned char>& fileBuf) { std::map<int,int> prevHashes; for (int a=0; a<num; a++) { if (a == excludePrim) { continue; } _Primitive p; int curOffset = pos + a * sizeof(_Primitive); READ_PRIMITIVE(p, fileBuf, curOffset); if (p.NumberOfVertexIndexes < 3) continue; S3DOPrimitive sp; sp.indices.resize(p.NumberOfVertexIndexes); sp.vnormals.resize(p.NumberOfVertexIndexes); // load vertex indices list curOffset = p.OffsetToVertexIndexArray; for (int b=0; b<p.NumberOfVertexIndexes; b++) { boost::uint16_t w; STREAM_READ(&w,2, fileBuf, curOffset); swabWordInPlace(w); sp.indices[b] = w; } // find texture sp.texture = GetTexture(obj, &p, fileBuf); // set the primitive-normal const float3 v0v1 = (obj->vertexPos[sp.indices[1]] - obj->vertexPos[sp.indices[0]]); const float3 v0v2 = (obj->vertexPos[sp.indices[2]] - obj->vertexPos[sp.indices[0]]); sp.primNormal = (-v0v1.cross(v0v2)).SafeANormalize(); // some 3dos got multiple baseplates a.k.a. `selection primitive` // it's not meant to be rendered, so hide it if (IsBasePlate(obj, &sp)) continue; // 3do has often duplicated faces (with equal geometry) // with different textures (e.g. for animations and other effects) // we don't support those, only render the last one std::vector<int> orderVert = sp.indices; std::sort(orderVert.begin(), orderVert.end()); const int vertHash = HsiehHash(&orderVert[0], orderVert.size() * sizeof(orderVert[0]), 0x123456); auto phi = prevHashes.find(vertHash); if (phi != prevHashes.end()) { obj->prims[phi->second] = sp; continue; } prevHashes[vertHash] = obj->prims.size(); obj->prims.push_back(sp); } }
// used only by ReadInfoMap (for unitsync) void CSMFMapFile::ReadHeightmap(unsigned short* heightmap) { const int hmx = header.mapx + 1; const int hmy = header.mapy + 1; ifs.Seek(header.heightmapPtr); ifs.Read(heightmap, hmx * hmy * sizeof(short)); for (int y = 0; y < hmx * hmy; ++y) { swabWordInPlace(heightmap[y]); } }