static void READ_VERTEX(float3& v, const std::vector<unsigned char>& fileBuf, int& curOffset) { unsigned int __tmp; unsigned short __isize = sizeof(unsigned int); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); v.x = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); v.y = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); v.z = (int)swabDWord(__tmp); }
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); } }
static std::string GET_TEXT(int pos, const std::vector<unsigned char>& fileBuf, int& curOffset) { curOffset = pos; std::string s; s.reserve(16); do { s.push_back(0); STREAM_READ(&s.back(), 1, fileBuf, curOffset); } while (s.back() != 0); s.pop_back(); // pop the \0 return s; }
static void READ_PRIMITIVE(C3DOParser::_Primitive& p, const std::vector<unsigned char>& fileBuf, int& curOffset) { unsigned int __tmp; unsigned short __isize = sizeof(unsigned int); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); p.PaletteEntry = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); p.NumberOfVertexIndexes = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); p.Always_0 = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); p.OffsetToVertexIndexArray = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); p.OffsetToTextureName = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); p.Unknown_1 = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); p.Unknown_2 = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); p.Unknown_3 = (int)swabDWord(__tmp); }
static void READ_3DOBJECT(C3DOParser::_3DObject& o, const std::vector<unsigned char>& fileBuf, int& curOffset) { unsigned int __tmp; unsigned short __isize = sizeof(unsigned int); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.VersionSignature = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.NumberOfVertices = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.NumberOfPrimitives = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.SelectionPrimitive = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.XFromParent = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.YFromParent = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.ZFromParent = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.OffsetToObjectName = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.Always_0 = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.OffsetToVertexArray = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.OffsetToPrimitiveArray = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.OffsetToSiblingObject = (int)swabDWord(__tmp); STREAM_READ(&__tmp,__isize, fileBuf, curOffset); o.OffsetToChildObject = (int)swabDWord(__tmp); }
/* delete a portion of an index, adjusting offset appropriately. Returns 0 if things work and we should be called again, 1 if success full and done, and -1 if an error occurred. It adjusts offset appropriately on 0 or 1 return codes, and otherwise doesn't touch it */ static int ObliterateRegion(Volume * avp, VnodeClass aclass, StreamHandle_t * afile, afs_int32 * aoffset) { register struct VnodeClassInfo *vcp; Inode inodes[MAXOBLITATONCE]; register afs_int32 iindex, nscanned; afs_int32 offset; char buf[SIZEOF_LARGEDISKVNODE]; int hitEOF; register int i; register afs_int32 code; register struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf; hitEOF = 0; vcp = &VnodeClassInfo[aclass]; offset = *aoffset; /* original offset */ iindex = 0; nscanned = 0; /* advance over up to MAXOBLITATONCE inodes. nscanned tells us how many we examined. * We remember the inodes in an array, and idec them after zeroing them in the index. * The reason for these contortions is to make volume deletion idempotent, even * if we crash in the middle of a delete operation. */ STREAM_SEEK(afile, offset, 0); while (1) { if (iindex >= MAXOBLITATONCE) { break; } code = STREAM_READ(vnode, vcp->diskSize, 1, afile); nscanned++; offset += vcp->diskSize; if (code != 1) { hitEOF = 1; break; } if (vnode->type != vNull) { if (vnode->vnodeMagic != vcp->magic) goto fail; /* something really wrong; let salvager take care of it */ if (VNDISK_GET_INO(vnode)) inodes[iindex++] = VNDISK_GET_INO(vnode); } } /* next, obliterate the index and fflush (and fsync) it */ STREAM_SEEK(afile, *aoffset, 0); /* seek back to start of vnode index region */ memset(buf, 0, sizeof(buf)); /* zero out our proto-vnode */ for (i = 0; i < nscanned; i++) { if (STREAM_WRITE(buf, vcp->diskSize, 1, afile) != 1) goto fail; } STREAM_FLUSH(afile); /* ensure 0s are on the disk */ OS_SYNC(afile->str_fd); /* finally, do the idec's */ for (i = 0; i < iindex; i++) { IH_DEC(V_linkHandle(avp), inodes[i], V_parentId(avp)); DOPOLL; } /* return the new offset */ *aoffset = offset; return hitEOF; /* return 1 if hit EOF (don't call again), otherwise 0 */ fail: return -1; }
Sprite* spr_Create(ILTStream *pStream) { uint32 nFrames, nFrameRate, bTransparent, bTranslucent, colourKey; uint32 i, iAnim; char s[1024]; Sprite *pSprite; SpriteAnim *pAnim; uint16 strLen; FileRef ref; pSprite = LTNULL; // Setup the Sprite. LT_MEM_TRACK_ALLOC(pSprite = (Sprite*)dalloc(sizeof(Sprite)),LT_MEM_TYPE_SPRITE); memset(pSprite, 0, sizeof(Sprite)); pSprite->m_Link.m_pData = pSprite; // Read in the animations pSprite->m_nAnims = 1; // Sprites only get one animation currently... LT_MEM_TRACK_ALLOC(pSprite->m_Anims = (SpriteAnim*)dalloc(sizeof(SpriteAnim) * pSprite->m_nAnims),LT_MEM_TYPE_SPRITE); memset(pSprite->m_Anims, 0, sizeof(SpriteAnim) * pSprite->m_nAnims); for(iAnim=0; iAnim < pSprite->m_nAnims; iAnim++) { pAnim = &pSprite->m_Anims[iAnim]; STREAM_READ(nFrames); STREAM_READ(nFrameRate); STREAM_READ(bTransparent); STREAM_READ(bTranslucent); STREAM_READ(colourKey); // Allocate array for resource ID's LT_MEM_TRACK_ALLOC(pAnim->m_Frames = (SpriteEntry*)dalloc(sizeof(SpriteEntry) * nFrames),LT_MEM_TYPE_SPRITE); // Record the name of the animation LTStrCpy(pAnim->m_sName, "Untitled", sizeof(pAnim->m_sName)); // Set the number of frames in this animation to zero pAnim->m_nFrames = nFrames; pAnim->m_MsFrameRate = nFrameRate; pAnim->m_MsAnimLength = (1000 / nFrameRate) * nFrames; pAnim->m_bKeyed = (uint8)bTransparent; pAnim->m_bTranslucent = (uint8)bTranslucent; pAnim->m_ColourKey = colourKey; // Read in the frames for the animation. for(i=0; i < nFrames; i++) { // Read in frame file name STREAM_READ(strLen); if(strLen > 1000) { spr_Destroy(pSprite); return LTNULL; } pStream->Read(s, strLen); s[strLen] = 0; ref.m_FileType = FILE_CLIENTFILE; ref.m_pFilename = s; pAnim->m_Frames[i].m_pTex = g_pClientMgr->AddSharedTexture(&ref); } } if(pStream->ErrorStatus() != LT_OK) { spr_Destroy(pSprite); return LTNULL; } else { return pSprite; } }