diff --git a/TODO b/TODO index d0ccf65..40f4c56 100644 --- a/TODO +++ b/TODO @@ -15,20 +15,24 @@ Clump & related: - implement plugins: Clump R* Collision + Animation (old III dffs) Atomic ((Particles)) R* Pipeline Set + Skin (old III dffs) Geometry - -Native Data ((Morph)) - -Skin R* 2dfx Material UV Anim Texture (Sky Mipmap Val) -- PDS Pipelines (at least dummies) +- PDS Pipelines + +- ADC + +- uninstance geometry - UV Anim Dict diff --git a/insttest.cpp b/insttest.cpp index 7762543..e9c1592 100644 --- a/insttest.cpp +++ b/insttest.cpp @@ -62,15 +62,6 @@ main(int argc, char *argv[]) // printf("%s\n", argv[arg]); -// only opengl: -/* - for(int32 i = 0; i < c->numAtomics; i++){ - Atomic *a = c->atomicList[i]; - gl::printPipeinfo(a); - } - return 0; -*/ - /* for(int32 i = 0; i < c->numAtomics; i++){ Atomic *a = c->atomicList[i]; @@ -93,9 +84,9 @@ main(int argc, char *argv[]) p->instance(a); } - data = new rw::uint8[256*1024]; + data = new rw::uint8[512*1024]; rw::StreamMemory out; - out.open(data, 0, 256*1024); + out.open(data, 0, 512*1024); c->streamWrite(&out); FILE *cf = fopen("out.dff", "wb"); diff --git a/src/geometry.cpp b/src/geometry.cpp index f012d04..8e8d2c9 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -270,6 +270,79 @@ Geometry::addMorphTargets(int32 n) this->numMorphTargets += n; } +void +Geometry::allocateData(void) +{ + if(this->geoflags & PRELIT) + this->colors = new uint8[4*this->numVertices]; + if((this->geoflags & TEXTURED) || (this->geoflags & TEXTURED2)) + for(int32 i = 0; i < this->numTexCoordSets; i++) + this->texCoords[i] = + new float32[2*this->numVertices]; + MorphTarget *m = this->morphTargets; + m->vertices = new float32[3*this->numVertices]; + if(this->geoflags & NORMALS) + m->normals = new float32[3*this->numVertices]; + // TODO: morph targets (who cares anyway?) +} + +static int +isDegenerate(uint16 *idx) +{ + // TODO: maybe check position instead of index? + return idx[0] == idx[1] || + idx[0] == idx[2] || + idx[1] == idx[2]; +} + +void +Geometry::generateTriangles(void) +{ + MeshHeader *header = this->meshHeader; + assert(header != NULL); + + this->numTriangles = 0; + Mesh *m = header->mesh; + for(uint32 i = 0; i < header->numMeshes; i++){ + if(header->flags == 1){ // tristrip + for(uint32 j = 0; j < m->numIndices-2; j++){ + if(!isDegenerate(&m->indices[j])) + this->numTriangles++; + } + }else + this->numTriangles += m->numIndices/3; + m++; + } + + delete[] this->triangles; + this->triangles = new uint16[4*this->numTriangles]; + printf("%d %p\n", this->numTriangles, this->triangles); + + uint16 *f = this->triangles; + m = header->mesh; + for(uint32 i = 0; i < header->numMeshes; i++){ + int32 matid = findPointer((void*)m->material, + (void**)this->materialList, + this->numMaterials); + if(header->flags == 1) // tristrip + for(uint32 j = 0; j < m->numIndices-2; j++){ + if(isDegenerate(&m->indices[j])) + continue; + *f++ = m->indices[j+1 + (j%2)]; + *f++ = m->indices[j+0]; + *f++ = matid; + *f++ = m->indices[j+2 - (j%2)]; + } + else + for(uint32 j = 0; j < m->numIndices-2; j+=3){ + *f++ = m->indices[j+1]; + *f++ = m->indices[j+0]; + *f++ = matid; + *f++ = m->indices[j+2]; + } + m++; + } +} // // Material diff --git a/src/ogl.cpp b/src/ogl.cpp index 577f79f..b89a0a3 100644 --- a/src/ogl.cpp +++ b/src/ogl.cpp @@ -176,7 +176,8 @@ packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale=1.0f) } ObjPipeline::ObjPipeline(uint32 platform) - : rw::ObjPipeline(platform), numCustomAttribs(0), instanceCB(NULL) { } + : rw::ObjPipeline(platform), numCustomAttribs(0), + instanceCB(NULL), uninstanceCB(NULL) { } void ObjPipeline::instance(Atomic *atomic) @@ -286,6 +287,7 @@ ObjPipeline::instance(Atomic *atomic) } if(geo->geoflags & Geometry::PRELIT){ + // TODO: this seems too complicated p = header->data + a->offset; uint8 *color = geo->colors; float32 f[4]; @@ -303,6 +305,132 @@ ObjPipeline::instance(Atomic *atomic) geo->geoflags |= Geometry::NATIVE; } +static void +unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale=1.0f) +{ + int8 *i8src; + uint16 *u16src; + int16 *i16src; + + switch(a->type){ + case 0: // float + memcpy(dst, src, a->size*4); + break; + + // TODO: maybe have loop inside if? + case 1: // byte + i8src = (int8*)src; + for(int i = 0; i < a->size; i++){ + if(!a->normalized) + dst[i] = i8src[i]/scale; + else + dst[i] = i8src[i]/127.0f; + } + break; + + case 2: // ubyte + for(int i = 0; i < a->size; i++){ + if(!a->normalized) + dst[i] = src[i]/scale; + else + dst[i] = src[i]/255.0f; + } + break; + + case 3: // short + i16src = (int16*)src; + for(int i = 0; i < a->size; i++){ + if(!a->normalized) + dst[i] = i16src[i]/scale; + else + dst[i] = i16src[i]/32767.0f; + } + break; + + case 4: // ushort + u16src = (uint16*)src; + for(int i = 0; i < a->size; i++){ + if(!a->normalized) + dst[i] = u16src[i]/scale; + else + dst[i] = u16src[i]/65435.0f; + } + break; + } +} + +void +ObjPipeline::uninstance(Atomic *atomic) +{ + Geometry *geo = atomic->geometry; + if((geo->geoflags & Geometry::NATIVE) == 0) + return; + geo->geoflags &= ~Geometry::NATIVE; + geo->allocateData(); + + uint8 *p; + float32 *texcoord = geo->texCoords[0]; + uint8 *color = geo->colors; + float32 *vert = geo->morphTargets->vertices; + float32 *norm = geo->morphTargets->normals; + float32 f[4]; + + InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; + for(int i = 0; i < header->numAttribs; i++){ + AttribDesc *a = &header->attribs[i]; + p = header->data + a->offset; + + switch(a->index){ + case 0: // Vertices + for(int32 i = 0; i < geo->numVertices; i++){ + unpackattrib(vert, p, a); + vert += 3; + p += a->stride; + } + break; + + case 1: // texCoords + for(int32 i = 0; i < geo->numVertices; i++){ + unpackattrib(texcoord, p, a, 512.0f); + texcoord += 2; + p += a->stride; + } + break; + + case 2: // normals + for(int32 i = 0; i < geo->numVertices; i++){ + unpackattrib(norm, p, a); + norm += 3; + p += a->stride; + } + break; + + case 3: // colors + for(int32 i = 0; i < geo->numVertices; i++){ + // TODO: this seems too complicated + unpackattrib(f, p, a); + color[0] = f[0]*255.0f; + color[1] = f[1]*255.0f; + color[2] = f[2]*255.0f; + color[3] = f[3]*255.0f; + color += 4; + p += a->stride; + } + break; + } + } + + if(this->uninstanceCB) + uninstanceCB(geo); + + geo->generateTriangles(); + + delete header->attribs; + delete header->data; + delete header; + geo->instData = NULL; +} + ObjPipeline* makeDefaultPipeline(void) { @@ -466,6 +594,46 @@ skinInstanceCB(Geometry *g, int32 i, uint32 offset) return 8; } +void +skinUninstanceCB(Geometry *geo) +{ + InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; + + Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); + if(skin == NULL) + return; + + skin->allocateVertexData(geo->numVertices); + + uint8 *p; + float *weights = skin->weights; + uint8 *indices = skin->indices; + for(int i = 0; i < header->numAttribs; i++){ + AttribDesc *a = &header->attribs[i]; + p = header->data + a->offset; + + switch(a->index){ + case 4: // weights + for(int32 i = 0; i < geo->numVertices; i++){ + unpackattrib(weights, p, a); + weights += 4; + p += a->stride; + } + break; + + case 5: // indices + for(int32 i = 0; i < geo->numVertices; i++){ + *indices++ = p[0]; + *indices++ = p[1]; + *indices++ = p[2]; + *indices++ = p[3]; + p += a->stride; + } + break; + } + } +} + ObjPipeline* makeSkinPipeline(void) { @@ -474,6 +642,7 @@ makeSkinPipeline(void) pipe->pluginData = 1; pipe->numCustomAttribs = 2; pipe->instanceCB = skinInstanceCB; + pipe->uninstanceCB = skinUninstanceCB; return pipe; } diff --git a/src/plugins.cpp b/src/plugins.cpp index 4abca04..8708ff7 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -62,9 +62,9 @@ readHAnim(Stream *stream, int32, void *object, int32 offset, int32) { int32 cnst, numNodes; HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset); - cnst = stream->readI32(); - if(cnst != 256){ - printf("hanim const was not 256\n"); + ver = stream->readI32(); + if(ver != 0x100){ + fprintf(stderr, "hanim ver was not 0x100\n"); return; } hanim->id = stream->readI32(); @@ -362,38 +362,13 @@ copySkin(void *dst, void *src, int32 offset, int32) dstskin->numBones = srcskin->numBones; dstskin->numUsedBones = srcskin->numUsedBones; dstskin->maxIndex = srcskin->maxIndex; - uint32 size = srcskin->numUsedBones + - srcskin->numBones*64 + - geometry->numVertices*(16+4) + 15; - uint8 *data = new uint8[size]; - dstskin->data = data; - memcpy(dstskin->data, srcskin->data, size); - - dstskin->usedBones = NULL; - if(srcskin->usedBones){ - dstskin->usedBones = data; - data += dstskin->numUsedBones; - } - - uintptr ptr = (uintptr)data + 15; - ptr &= ~0xF; - data = (uint8*)ptr; - dstskin->inverseMatrices = NULL; - if(srcskin->inverseMatrices){ - dstskin->inverseMatrices = (float*)data; - data += 64*dstskin->numBones; - } - - dstskin->indices = NULL; - if(srcskin->indices){ - dstskin->indices = data; - data += 4*geometry->numVertices; - } - - dstskin->weights = NULL; - if(srcskin->weights) - dstskin->weights = (float*)data; + dstskin->allocateData(geometry->numVertices); + memcpy(dstskin->usedBones, srcskin->usedBones, srcskin->numUsedBones); + memcpy(dstskin->inverseMatrices, srcskin->inverseMatrices, + srcskin->numBones*64); + memcpy(dstskin->indices, srcskin->indices, geometry->numVertices*4); + memcpy(dstskin->weights, srcskin->weights, geometry->numVertices*16); return dst; } @@ -422,37 +397,9 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32) skin->numUsedBones = header[1]; skin->maxIndex = header[2]; + // probably rw::version >= 0x34000 bool oldFormat = skin->numUsedBones == 0; - uint32 size = skin->numUsedBones + - skin->numBones*64 + - geometry->numVertices*(16+4) + 15; - uint8 *data = new uint8[size]; - skin->data = data; - - skin->usedBones = NULL; - if(skin->numUsedBones){ - skin->usedBones = data; - data += skin->numUsedBones; - } - - uintptr ptr = (uintptr)data + 15; - ptr &= ~0xF; - data = (uint8*)ptr; - skin->inverseMatrices = NULL; - if(skin->numBones){ - skin->inverseMatrices = (float*)data; - data += 64*skin->numBones; - } - - skin->indices = NULL; - if(geometry->numVertices){ - skin->indices = data; - data += 4*geometry->numVertices; - } - - skin->weights = NULL; - if(geometry->numVertices) - skin->weights = (float*)data; + skin->allocateData(geometry->numVertices); if(skin->usedBones) stream->read(skin->usedBones, skin->numUsedBones); @@ -569,6 +516,55 @@ registerSkinPlugin(void) Atomic::setStreamRightsCallback(ID_SKIN, skinRights); } +void +Skin::allocateData(int32 numVerts) +{ + uint32 size = this->numUsedBones + + this->numBones*64 + + numVerts*(16+4) + 15; + this->data = new uint8[size]; + uint8 *data = this->data; + + this->usedBones = NULL; + if(this->numUsedBones){ + this->usedBones = data; + data += this->numUsedBones; + } + + uintptr ptr = (uintptr)data + 15; + ptr &= ~0xF; + data = (uint8*)ptr; + this->inverseMatrices = NULL; + if(this->numBones){ + this->inverseMatrices = (float*)data; + data += 64*this->numBones; + } + + this->indices = NULL; + if(numVerts){ + this->indices = data; + data += 4*numVerts; + } + + this->weights = NULL; + if(numVerts) + this->weights = (float*)data; + +} + +void +Skin::allocateVertexData(int32 numVerts) +{ + uint8 *usedBones = this->usedBones; + float *invMats = this->inverseMatrices; + uint8 *data = this->data; + + this->allocateData(numVerts); + memcpy(this->usedBones, usedBones, this->numUsedBones); + memcpy(this->inverseMatrices, invMats, this->numBones*64); + delete[] data; +} + // // MatFX // @@ -612,6 +608,7 @@ writeAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32) static int32 getSizeAtomicMatFX(void *object, int32 offset, int32) { + // TODO: version dependent /* int32 flag; flag = *PLUGINOFFSET(int32, object, offset); return flag ? 4 : -1; */ diff --git a/src/rwobjects.h b/src/rwobjects.h index 63ac3ca..b1555a7 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -289,6 +289,8 @@ struct Geometry : PluginBase, Object bool streamWrite(Stream *stream); uint32 streamGetSize(void); void addMorphTargets(int32 n); + void allocateData(void); + void generateTriangles(void); enum Flags { @@ -318,6 +320,9 @@ struct Skin uint8 *indices; float *weights; uint8 *data; // only used by delete + + void allocateData(int32 numVerts); + void allocateVertexData(int32 numVerts); }; struct SkinGlobals diff --git a/src/rwogl.h b/src/rwogl.h index 9352703..4c0bbe9 100644 --- a/src/rwogl.h +++ b/src/rwogl.h @@ -39,9 +39,11 @@ class ObjPipeline : public rw::ObjPipeline public: uint32 numCustomAttribs; uint32 (*instanceCB)(Geometry *g, int32 i, uint32 offset); + void (*uninstanceCB)(Geometry *g); ObjPipeline(uint32 platform); virtual void instance(Atomic *atomic); + virtual void uninstance(Atomic *atomic); }; ObjPipeline *makeDefaultPipeline(void);