From d20a6c3d0444a18e992142121354d35755b9ec8b Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 24 Jan 2016 01:42:51 +0100 Subject: [PATCH] some changes --- librw.sln | 1 + librw.vcxproj | 1 + src/anim.cpp | 7 +- src/clump.cpp | 35 ++++-- src/geometry.cpp | 84 ++++++++++--- src/gtaplg.cpp | 25 ++-- src/gtaplg.h | 9 ++ src/image.cpp | 18 +-- src/plugins.cpp | 216 +++++++++++++++++++++++++------- src/ps2.cpp | 27 ++-- src/rwbase.cpp | 46 ++++++- src/rwbase.h | 3 + src/rwobjects.h | 53 +++++++- src/rwps2.h | 14 +-- tools/insttest/insttest.cpp | 58 ++++++++- tools/insttest/insttest.vcxproj | 5 +- tools/rsltest/rsltest.cpp | 125 ++++++++++++++++-- 17 files changed, 591 insertions(+), 136 deletions(-) diff --git a/librw.sln b/librw.sln index 8dea99e..7149c60 100644 --- a/librw.sln +++ b/librw.sln @@ -85,6 +85,7 @@ Global {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.ActiveCfg = Release|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.Build.0 = Release|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.ActiveCfg = Release|x64 + {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.Build.0 = Release|x64 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|x64.ActiveCfg = Debug - null|x64 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.ActiveCfg = Debug|Win32 diff --git a/librw.vcxproj b/librw.vcxproj index 4376ed2..645d99f 100644 --- a/librw.vcxproj +++ b/librw.vcxproj @@ -149,6 +149,7 @@ Disabled true _USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL true diff --git a/src/anim.cpp b/src/anim.cpp index 31be01c..7694602 100644 --- a/src/anim.cpp +++ b/src/anim.cpp @@ -301,11 +301,6 @@ registerUVAnimInterpolator(void) int32 uvAnimOffset; -struct UVAnim -{ - AnimInterpolator *interp[8]; -}; - static void* createUVAnim(void *object, int32 offset, int32) { @@ -367,7 +362,7 @@ makeDummyAnimation(const char *name) static void readUVAnim(Stream *stream, int32, void *object, int32 offset, int32) { - UVAnim *uvanim = PLUGINOFFSET(UVAnim, object, offset); + UVAnim *uvanim = PLUGINOFFSET(UVAnim, object, offset); assert(findChunk(stream, ID_STRUCT, NULL, NULL)); char name[32]; uint32 mask = stream->readI32(); diff --git a/src/clump.cpp b/src/clump.cpp index 75d450d..7db9b03 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -88,16 +88,21 @@ Frame::destroyHierarchy(void) } Frame* -Frame::addChild(Frame *child) +Frame::addChild(Frame *child, bool32 append) { - if(this->child == NULL) + if(append){ + if(this->child == NULL) + this->child = child; + else{ + Frame *f; + for(f = this->child; f->next; f = f->next); + f->next = child; + } + child->next = NULL; + }else{ + child->next = this->child; this->child = child; - else{ - Frame *f; - for(f = this->child; f->next; f = f->next); - f->next = child; } - child->next = NULL; child->object.parent = this; child->root = this->root; return this; @@ -364,7 +369,8 @@ Clump::streamWrite(Stream *stream) writeChunkHeader(stream, ID_CLUMP, size); int32 numAtomics = this->countAtomics(); int32 numLights = this->countLights(); - int buf[3] = { numAtomics, numLights, 0 }; + int32 numCameras = this->countCameras(); + int buf[3] = { numAtomics, numLights, numCameras }; size = version > 0x33000 ? 12 : 4; writeChunkHeader(stream, ID_STRUCT, size); stream->write(buf, size); @@ -372,7 +378,6 @@ Clump::streamWrite(Stream *stream) int32 numFrames = this->getFrame()->count(); Frame **flist = new Frame*[numFrames]; makeFrameList(this->getFrame(), flist); - this->frameListStreamWrite(stream, flist, numFrames); if(rw::version >= 0x30400){ @@ -550,6 +555,18 @@ Atomic::create(void) atomic->geometry = NULL; atomic->pipeline = NULL; atomic->constructPlugins(); + + // flags: + // rpATOMICCOLLISIONTEST = 0x01, /**numTexCoordSets; i++) geo->texCoords[i] = new float32[2*geo->numVertices]; - geo->triangles = new uint16[4*geo->numTriangles]; + geo->triangles = new Triangle[geo->numTriangles]; } geo->morphTargets = new MorphTarget[1]; MorphTarget *m = geo->morphTargets; @@ -77,7 +77,7 @@ Geometry::destroy(void) for(int32 i = 0; i < this->numTexCoordSets; i++) delete[] this->texCoords[i]; delete[] this->triangles; - + for(int32 i = 0; i < this->numMorphTargets; i++){ MorphTarget *m = &this->morphTargets[i]; delete[] m->vertices; @@ -120,7 +120,14 @@ Geometry::streamRead(Stream *stream) for(int32 i = 0; i < geo->numTexCoordSets; i++) stream->read(geo->texCoords[i], 2*geo->numVertices*4); - stream->read(geo->triangles, 4*geo->numTriangles*2); + for(int32 i = 0; i < geo->numTriangles; i++){ + uint32 tribuf[2]; + stream->read(tribuf, 8); + geo->triangles[i].v[0] = tribuf[0] >> 16; + geo->triangles[i].v[1] = tribuf[0]; + geo->triangles[i].v[2] = tribuf[1] >> 16; + geo->triangles[i].matId = tribuf[1]; + } } for(int32 i = 0; i < geo->numMorphTargets; i++){ @@ -200,7 +207,14 @@ Geometry::streamWrite(Stream *stream) for(int32 i = 0; i < this->numTexCoordSets; i++) stream->write(this->texCoords[i], 2*this->numVertices*4); - stream->write(this->triangles, 4*this->numTriangles*2); + for(int32 i = 0; i < this->numTriangles; i++){ + uint32 tribuf[2]; + tribuf[0] = this->triangles[i].v[0] << 16 | + this->triangles[i].v[1]; + tribuf[1] = this->triangles[i].v[2] << 16 | + this->triangles[i].matId; + stream->write(tribuf, 8); + } } for(int32 i = 0; i < this->numMorphTargets; i++){ @@ -363,9 +377,9 @@ Geometry::generateTriangles(int8 *adc) } delete[] this->triangles; - this->triangles = new uint16[4*this->numTriangles]; + this->triangles = new Triangle[this->numTriangles]; - uint16 *f = this->triangles; + Triangle *tri = this->triangles; m = header->mesh; adcbits = adc; for(uint32 i = 0; i < header->numMeshes; i++){ @@ -382,23 +396,65 @@ Geometry::generateTriangles(int8 *adc) if(adc && adcbits[j+2] || 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)]; + tri->v[0] = m->indices[j+0]; + tri->v[1] = m->indices[j+1 + (j%2)]; + tri->v[2] = m->indices[j+2 - (j%2)]; + tri->matId = matid; + tri++; } 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]; + tri->v[0] = m->indices[j+0]; + tri->v[1] = m->indices[j+1]; + tri->v[2] = m->indices[j+2]; + tri->matId = matid; } adcbits += m->numIndices; m++; } } +void +Geometry::buildMeshes(void) +{ + delete this->meshHeader; + + Triangle *tri; + MeshHeader *h = new MeshHeader; + this->meshHeader = h; + if((this->geoflags & Geometry::TRISTRIP) == 0){ + h->flags = 0; + h->totalIndices = this->numTriangles*3; + h->numMeshes = this->numMaterials; + h->mesh = new Mesh[h->numMeshes]; + for(uint32 i = 0; i < h->numMeshes; i++){ + h->mesh[i].material = this->materialList[i]; + h->mesh[i].numIndices = 0; + } + // count indices per mesh + tri = this->triangles; + for(int32 i = 0; i < this->numTriangles; i++){ + h->mesh[tri->matId].numIndices += 3; + tri++; + } + h->allocateIndices(); + for(uint32 i = 0; i < h->numMeshes; i++) + h->mesh[i].numIndices = 0; + // same as above but fill with indices + tri = this->triangles; + for(int32 i = 0; i < this->numTriangles; i++){ + uint32 idx = h->mesh[tri->matId].numIndices; + h->mesh[tri->matId].indices[idx++] = tri->v[0]; + h->mesh[tri->matId].indices[idx++] = tri->v[1]; + h->mesh[tri->matId].indices[idx++] = tri->v[2]; + h->mesh[tri->matId].numIndices = idx; + tri++; + } + }else{ + assert(0 && "can't tristrip\n"); + } +} + // // Material // diff --git a/src/gtaplg.cpp b/src/gtaplg.cpp index 3a0ef20..1846b23 100644 --- a/src/gtaplg.cpp +++ b/src/gtaplg.cpp @@ -61,6 +61,9 @@ attachPlugins(void) rw::ps2::registerNativeRaster(); rw::xbox::registerNativeRaster(); rw::d3d::registerNativeRaster(); + int32 nativeRasterOffset = Raster::registerPlugin(sizeof(NativeRaster), + 0x12340000 | PLATFORM_NULL, NULL, NULL, NULL); + Raster::nativeOffsets[PLATFORM_NULL] = nativeRasterOffset; rw::registerMeshPlugin(); rw::registerNativeDataPlugin(); @@ -873,13 +876,6 @@ static bool hasColors2(uint32 id) return id == 0x53f20083 || id == 0x53f2008f; } -struct SaVert : ps2::Vertex { - float32 w[4]; - uint8 i[4]; - float32 t1[2]; - uint8 c1[4]; -}; - static void saPreCB(MatPipeline *p, Geometry *geo) { @@ -916,27 +912,28 @@ findSAVertex(Geometry *g, uint32 flags[], uint32 mask, SaVert *v) cols1 = PLUGINOFFSET(ExtraVertColors, g, extraVertColorOffset)->nightColors; for(int32 i = 0; i < g->numVertices; i++){ - if(mask & flags[i] & 0x1 && + uint32 flag = flags ? flags[i] : ~0; + if(mask & flag & 0x1 && !(verts[0] == v->p[0] && verts[1] == v->p[1] && verts[2] == v->p[2])) goto cont; - if(mask & flags[i] & 0x10 && + if(mask & flag & 0x10 && !(norms[0] == v->n[0] && norms[1] == v->n[1] && norms[2] == v->n[2])) goto cont; - if(mask & flags[i] & 0x100 && + if(mask & flag & 0x100 && !(cols0[0] == v->c[0] && cols0[1] == v->c[1] && cols0[2] == v->c[2] && cols0[3] == v->c[3])) goto cont; - if(mask & flags[i] & 0x200 && + if(mask & flag & 0x200 && !(cols1[0] == v->c1[0] && cols1[1] == v->c1[1] && cols1[2] == v->c1[2] && cols1[3] == v->c1[3])) goto cont; - if(mask & flags[i] & 0x1000 && + if(mask & flag & 0x1000 && !(tex0[0] == v->t[0] && tex0[1] == v->t[1])) goto cont; - if(mask & flags[i] & 0x2000 && + if(mask & flag & 0x2000 && !(tex1[0] == v->t1[0] && tex1[1] == v->t1[1])) goto cont; - if(mask & flags[i] & 0x10000 && + if(mask & flag & 0x10000 && !(wghts[0] == v->w[0] && wghts[1] == v->w[1] && wghts[2] == v->w[2] && wghts[3] == v->w[3] && inds[0] == v->i[0] && inds[1] == v->i[1] && diff --git a/src/gtaplg.h b/src/gtaplg.h index 3a81ad8..4322af9 100644 --- a/src/gtaplg.h +++ b/src/gtaplg.h @@ -124,6 +124,15 @@ void registerCollisionPlugin(void); // PDS pipes +struct SaVert : ps2::Vertex { + float32 w[4]; + uint8 i[4]; + float32 t1[2]; + uint8 c1[4]; +}; +void insertSAVertex(Geometry *geo, int32 i, uint32 mask, SaVert *v); +int32 findSAVertex(Geometry *g, uint32 flags[], uint32 mask, SaVert *v); + void registerPDSPipes(void); } diff --git a/src/image.cpp b/src/image.cpp index a161a7f..99a5eb8 100755 --- a/src/image.cpp +++ b/src/image.cpp @@ -170,7 +170,7 @@ Texture* Texture::streamRead(Stream *stream) { uint32 length; - char name[32], mask[32]; + char name[128], mask[128]; assert(findChunk(stream, ID_STRUCT, NULL, NULL)); uint32 filterAddressing = stream->readU32(); // TODO: if V addressing is 0, copy U @@ -197,18 +197,22 @@ bool Texture::streamWrite(Stream *stream) { int size; + char buf[36]; writeChunkHeader(stream, ID_TEXTURE, this->streamGetSize()); writeChunkHeader(stream, ID_STRUCT, 4); stream->writeU32(this->filterAddressing); - // TODO: length can't be > 32 - size = strlen(this->name)+4 & ~3; + memset(buf, 0, 36); + strncpy(buf, this->name, 32); + size = strlen(buf)+4 & ~3; writeChunkHeader(stream, ID_STRING, size); - stream->write(this->name, size); + stream->write(buf, size); - size = strlen(this->mask)+4 & ~3; + memset(buf, 0, 36); + strncpy(buf, this->mask, 32); + size = strlen(buf)+4 & ~3; writeChunkHeader(stream, ID_STRING, size); - stream->write(this->mask, size); + stream->write(buf, size); this->streamWritePlugins(stream); return true; @@ -640,7 +644,7 @@ Raster::calculateNumLevels(int32 width, int32 height) Raster* Raster::createFromImage(Image *image) { - assert(0 && "unsupported atm"); + assert(0 && "cannot create raster from image"); int32 format; // TODO: make that into a function if(image->depth == 32) diff --git a/src/plugins.cpp b/src/plugins.cpp index af905f2..7868d0f 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -24,6 +24,101 @@ namespace rw { // int32 hAnimOffset; +bool32 hAnimDoStream = 1; + +HAnimHierarchy* +HAnimHierarchy::create(int32 numNodes, int32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize) +{ + HAnimHierarchy *hier = (HAnimHierarchy*)malloc(sizeof(*hier)); + + hier->numNodes = numNodes; + hier->flags = flags; + hier->maxInterpKeyFrameSize = maxKeySize; + hier->parentFrame = NULL; + hier->parentHierarchy = hier; + if(hier->flags & 2) + hier->matrices = hier->matricesUnaligned = NULL; + else{ + hier->matricesUnaligned = + (float*) new uint8[hier->numNodes*64 + 15]; + hier->matrices = + (float*)((uintptr)hier->matricesUnaligned & ~0xF); + } + hier->nodeInfo = new HAnimNodeInfo[hier->numNodes]; + for(int32 i = 0; i < hier->numNodes; i++){ + hier->nodeInfo[i].id = nodeIDs[i]; + hier->nodeInfo[i].index = i; + hier->nodeInfo[i].flags = nodeFlags[i]; + hier->nodeInfo[i].frame = NULL; + } + return hier; +} + +void +HAnimHierarchy::destroy(void) +{ + delete[] (uint8*)this->matricesUnaligned; + delete[] this->nodeInfo; + free(this); +} + +static Frame* +findById(Frame *f, int32 id) +{ + if(f == NULL) return NULL; + HAnimData *hanim = HAnimData::get(f); + if(hanim->id >= 0 && hanim->id == id) return f; + Frame *ff = findById(f->next, id); + if(ff) return ff; + return findById(f->child, id); +} + +void +HAnimHierarchy::attachByIndex(int32 idx) +{ + int32 id = this->nodeInfo[idx].id; + Frame *f = findById(this->parentFrame, id); + this->nodeInfo[idx].frame = f; +} + +void +HAnimHierarchy::attach(void) +{ + for(int32 i = 0; i < this->numNodes; i++) + this->attachByIndex(i); +} + +int32 +HAnimHierarchy::getIndex(int32 id) +{ + for(int32 i = 0; i < this->numNodes; i++) + if(this->nodeInfo[i].id == id) + return i; + return -1; +} + +HAnimHierarchy* +HAnimHierarchy::get(Frame *f) +{ + return HAnimData::get(f)->hierarchy; +} + +HAnimHierarchy* +HAnimHierarchy::find(Frame *f) +{ + if(f == NULL) return NULL; + HAnimHierarchy *hier = HAnimHierarchy::get(f); + if(hier) return hier; + hier = HAnimHierarchy::find(f->next); + if(hier) return hier; + return HAnimHierarchy::find(f->child); +} + +HAnimData* +HAnimData::get(Frame *f) +{ + return PLUGINOFFSET(HAnimData, f, hAnimOffset); +} static void* createHAnim(void *object, int32 offset, int32) @@ -38,12 +133,8 @@ static void* destroyHAnim(void *object, int32 offset, int32) { HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset); - if(hanim->hierarchy){ - HAnimHierarchy *hier = hanim->hierarchy; - delete[] (uint8*)hier->matricesUnaligned; - delete[] hier->nodeInfo; - delete hier; - } + if(hanim->hierarchy) + hanim->hierarchy->destroy(); hanim->id = -1; hanim->hierarchy = NULL; return object; @@ -70,28 +161,20 @@ readHAnim(Stream *stream, int32, void *object, int32 offset, int32) hanim->id = stream->readI32(); numNodes = stream->readI32(); if(numNodes != 0){ - HAnimHierarchy *hier = new HAnimHierarchy; - hanim->hierarchy = hier; - hier->numNodes = numNodes; - hier->flags = stream->readI32(); - hier->maxInterpKeyFrameSize = stream->readI32(); - hier->parentFrame = (Frame*)object; - hier->parentHierarchy = hier; - if(hier->flags & 2) - hier->matrices = hier->matricesUnaligned = NULL; - else{ - hier->matricesUnaligned = - (float*) new uint8[hier->numNodes*64 + 15]; - hier->matrices = - (float*)((uintptr)hier->matricesUnaligned & ~0xF); - } - hier->nodeInfo = new HAnimNodeInfo[hier->numNodes]; - for(int32 i = 0; i < hier->numNodes; i++){ - hier->nodeInfo[i].id = stream->readI32(); - hier->nodeInfo[i].index = stream->readI32(); - hier->nodeInfo[i].flags = stream->readI32(); - hier->nodeInfo[i].frame = NULL; + int32 flags = stream->readI32(); + int32 maxKeySize = stream->readI32(); + int32 *nodeFlags = new int32[numNodes]; + int32 *nodeIDs = new int32[numNodes]; + for(int32 i = 0; i < numNodes; i++){ + nodeIDs[i] = stream->readI32(); + stream->readI32(); // index...unused + nodeFlags[i] = stream->readI32(); } + hanim->hierarchy = HAnimHierarchy::create(numNodes, + nodeFlags, nodeIDs, flags, maxKeySize); + hanim->hierarchy->parentFrame = (Frame*)object; + delete[] nodeFlags; + delete[] nodeIDs; } } @@ -121,8 +204,9 @@ getSizeHAnim(void *object, int32 offset, int32) { HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset); // TODO: version correct? - if(version >= 0x35000 && hanim->id == -1 && hanim->hierarchy == NULL) - return -1; + if(!hAnimDoStream || + version >= 0x35000 && hanim->id == -1 && hanim->hierarchy == NULL) + return 0; if(hanim->hierarchy) return 12 + 8 + hanim->hierarchy->numNodes*12; return 12; @@ -605,7 +689,7 @@ getSizeSkin(void *object, int32 offset, int32) static void skinRights(void *object, int32, int32, uint32) { - ((Atomic*)object)->pipeline = skinGlobals.pipelines[rw::platform]; + Skin::setPipeline((Atomic*)object, 1); } void @@ -712,6 +796,13 @@ Skin::findUsedBones(int32 numVertices) this->usedBones[this->numUsedBones++] = i; } +void +Skin::setPipeline(Atomic *a, int32 type) +{ + (void)type; + a->pipeline = skinGlobals.pipelines[rw::platform]; +} + // // MatFX // @@ -728,28 +819,22 @@ createAtomicMatFX(void *object, int32 offset, int32) static void* copyAtomicMatFX(void *dst, void *src, int32 offset, int32) { - *PLUGINOFFSET(int32, dst, offset) = *PLUGINOFFSET(int32, src, offset); + if(*PLUGINOFFSET(int32, src, offset)) + MatFX::enableEffects((Atomic*)dst); return dst; } static void readAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32) { - int32 flag; - stream->read(&flag, 4); -// printf("matfx: %d\n", flag); - *PLUGINOFFSET(int32, object, offset) = flag; - if(flag) - ((Atomic*)object)->pipeline = - matFXGlobals.pipelines[rw::platform]; + if(stream->readI32()) + MatFX::enableEffects((Atomic*)object); } static void writeAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32) { - int32 flag; - flag = *PLUGINOFFSET(int32, object, offset); - stream->writeI32(flag); + stream->writeI32(*PLUGINOFFSET(int32, object, offset)); } static int32 @@ -826,6 +911,22 @@ MatFX::getEffectIndex(uint32 type) return -1; } +void +MatFX::setBumpTexture(Texture *t) +{ + int32 i = this->getEffectIndex(BUMPMAP); + if(i >= 0) + this->fx[i].bump.tex = t; +} + +void +MatFX::setBumpCoefficient(float32 coef) +{ + int32 i = this->getEffectIndex(BUMPMAP); + if(i >= 0) + this->fx[i].bump.coefficient = coef; +} + void MatFX::setEnvTexture(Texture *t) { @@ -842,6 +943,30 @@ MatFX::setEnvCoefficient(float32 coef) this->fx[i].env.coefficient = coef; } +void +MatFX::setDualTexture(Texture *t) +{ + int32 i = this->getEffectIndex(DUAL); + if(i >= 0) + this->fx[i].dual.tex = t; +} + +void +MatFX::setDualSrcBlend(int32 blend) +{ + int32 i = this->getEffectIndex(DUAL); + if(i >= 0) + this->fx[i].dual.srcBlend = blend; +} + +void +MatFX::setDualDestBlend(int32 blend) +{ + int32 i = this->getEffectIndex(DUAL); + if(i >= 0) + this->fx[i].dual.dstBlend = blend; +} + static void* createMaterialMatFX(void *object, int32 offset, int32) { @@ -1038,11 +1163,18 @@ getSizeMaterialMatFX(void *object, int32 offset, int32) return size; } +void +MatFX::enableEffects(Atomic *atomic) +{ + *PLUGINOFFSET(int32, atomic, matFXGlobals.atomicOffset) = 1; + atomic->pipeline = matFXGlobals.pipelines[rw::platform]; +} + void registerMatFXPlugin(void) { ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); - defpipe->pluginID = ID_MATFX; + defpipe->pluginID = 0; //ID_MATFX; defpipe->pluginData = 0; for(uint i = 0; i < nelem(matFXGlobals.pipelines); i++) matFXGlobals.pipelines[i] = defpipe; diff --git a/src/ps2.cpp b/src/ps2.cpp index d9ab612..3dd1f2a 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -233,6 +233,8 @@ static uint32 getBatchSize(MatPipeline *pipe, uint32 vertCount) { PipeAttribute *a; + if(vertCount == 0) + return 0; uint32 size = 1; // ITOP &c. at the end for(uint i = 0; i < nelem(pipe->attribs); i++) if((a = pipe->attribs[i]) && (a->attrib & AT_RW) == 0){ @@ -393,21 +395,22 @@ getInstMeshInfo(MatPipeline *pipe, Geometry *g, Mesh *m) im.numAttribs++; } uint32 totalVerts = 0; - if(g->meshHeader->flags == 1){ // tristrip - im.numBatches = 0; - for(uint i = 0; i < m->numIndices; i += pipe->triStripCount-2){ - im.numBatches++; - totalVerts += m->numIndices-i < pipe->triStripCount ? - m->numIndices-i : pipe->triStripCount; - } + if(g->meshHeader->flags == MeshHeader::TRISTRIP){ + im.numBatches = (m->numIndices-2) / (pipe->triStripCount-2); im.batchVertCount = pipe->triStripCount; - im.lastBatchVertCount = totalVerts % pipe->triStripCount; - }else{ // trilist + im.lastBatchVertCount = (m->numIndices-2) % (pipe->triStripCount-2); + if(im.lastBatchVertCount){ + im.numBatches++; + im.lastBatchVertCount += 2; + } + }else{ im.numBatches = (m->numIndices+pipe->triListCount-1) / pipe->triListCount; im.batchVertCount = pipe->triListCount; im.lastBatchVertCount = m->numIndices % pipe->triListCount; } + if(im.lastBatchVertCount == 0) + im.lastBatchVertCount = im.batchVertCount; im.batchSize = getBatchSize(pipe, im.batchVertCount); im.lastBatchSize = getBatchSize(pipe, im.lastBatchVertCount); @@ -572,8 +575,10 @@ MatPipeline::collectData(Geometry *g, InstanceData *inst, Mesh *m, uint8 *data[] if((a = this->attribs[i]) && (a->attrib & AT_RW) == 0){ uint32 asz = attribSize(a->attrib); p += 4; - if((p[-1] & 0xff004000) != a->attrib) - printf("unexpected unpack: %08x %08x\n", p[-1], a->attrib); + if((p[-1] & 0xff004000) != a->attrib){ + fprintf(stderr, "unexpected unpack xx: %08x %08x\n", p[-1], a->attrib); + assert(0 && "unexpected unpack\n"); + } memcpy(datap[i], p, asz*nverts); datap[i] += asz*(nverts-overlap); p += QWC(asz*nverts)*4; diff --git a/src/rwbase.cpp b/src/rwbase.cpp index 89662ba..ec3cd69 100644 --- a/src/rwbase.cpp +++ b/src/rwbase.cpp @@ -25,6 +25,16 @@ int32 build = 0xFFFF; #endif char *debugFile = NULL; +void +matrixIdentify(float32 *mat) +{ + memset(mat, 0, 64); + mat[0] = 1.0f; + mat[5] = 1.0f; + mat[10] = 1.0f; + mat[16] = 1.0f; +} + void matrixMult(float32 *out, float32 *a, float32 *b) { @@ -32,17 +42,41 @@ matrixMult(float32 *out, float32 *a, float32 *b) #define L(i,j) out[i*4+j] #define A(i,j) a[i*4+j] #define B(i,j) b[i*4+j] - for(int i = 0; i < 4; i++) - for(int j = 0; j < 4; j++) - L(i,j) = A(0,j)*B(i,0) - + A(1,j)*B(i,1) - + A(2,j)*B(i,2) - + A(3,j)*B(i,3); + for(int i = 0; i < 4; i++) + for(int j = 0; j < 4; j++) + L(i,j) = A(0,j)*B(i,0) + + A(1,j)*B(i,1) + + A(2,j)*B(i,2) + + A(3,j)*B(i,3); #undef L #undef A #undef B } +void +vecTrans(float32 *out, float32 *mat, float32 *vec) +{ + #define M(i,j) mat[i*4+j] + for(int i = 0; i < 4; i++) + out[i] = M(0,i)*vec[0] + + M(1,i)*vec[1] + + M(2,i)*vec[2] + + M(3,i)*vec[3]; + #undef M +} + +void +matrixTranspose(float32 *out, float32 *in) +{ + #define OUT(i,j) out[i*4+j] + #define IN(i,j) in[i*4+j] + for(int i = 0; i < 4; i++) + for(int j = 0; j < 4; j++) + OUT(i,j) = IN(j,i); + #undef IN + #undef OUT +} + void matrixInvert(float32 *out, float32 *m) { diff --git a/src/rwbase.h b/src/rwbase.h index 5e993f5..a285174 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -153,7 +153,10 @@ extern int build; extern int platform; extern char *debugFile; +void matrixIdentify(float32 *mat); void matrixMult(float32 *out, float32 *a, float32 *b); +void vecTrans(float32 *out, float32 *mat, float32 *vec); +void matrixTranspose(float32 *out, float32 *in); void matrixInvert(float32 *out, float32 *in); // 0x04000000 3.1 diff --git a/src/rwobjects.h b/src/rwobjects.h index 163b0eb..70be9ee 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -132,7 +132,7 @@ struct Frame : PluginBase Frame *cloneHierarchy(void); void destroy(void); void destroyHierarchy(void); - Frame *addChild(Frame *f); + Frame *addChild(Frame *f, bool32 append = 0); Frame *removeChild(void); Frame *forAllChildren(Callback cb, void *data); Frame *getParent(void){ @@ -144,6 +144,13 @@ struct Frame : PluginBase void setHierarchyRoot(Frame *root); Frame *cloneAndLink(Frame *clonedroot); void purgeClone(void); + + // private flags: + // #define rwFRAMEPRIVATEHIERARCHYSYNCLTM 0x01 + // #define rwFRAMEPRIVATEHIERARCHYSYNCOBJ 0x02 + // #define rwFRAMEPRIVATESUBTREESYNCLTM 0x04 + // #define rwFRAMEPRIVATESUBTREESYNCOBJ 0x08 + // #define rwFRAMEPRIVATESTATIC 0x10 }; Frame **makeFrameList(Frame *frame, Frame **flist); @@ -191,15 +198,32 @@ struct HAnimHierarchy // temporary int32 maxInterpKeyFrameSize; + + static HAnimHierarchy *create(int32 numNodes, int32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize); + void destroy(void); + void attachByIndex(int32 id); + void attach(void); + int32 getIndex(int32 id); + + static HAnimHierarchy *get(Frame *f); + static HAnimHierarchy *find(Frame *f); + + enum NodeFlag { + POP = 1, + PUSH + }; }; struct HAnimData { int32 id; HAnimHierarchy *hierarchy; + + static HAnimData *get(Frame *f); }; extern int32 hAnimOffset; +extern bool32 hAnimDoStream; void registerHAnimPlugin(void); struct Image @@ -362,7 +386,7 @@ struct MatFX NOTHING = 0, BUMPMAP, ENVMAP, - BUMPENVMAP, + BUMPENVMAP, // BUMP | ENV DUAL, UVTRANSFORM, DUALUVTRANSFORM @@ -401,8 +425,15 @@ struct MatFX void setEffects(uint32 flags); int32 getEffectIndex(uint32 type); + void setBumpTexture(Texture *t); + void setBumpCoefficient(float32 coef); void setEnvTexture(Texture *t); void setEnvCoefficient(float32 coef); + void setDualTexture(Texture *t); + void setDualSrcBlend(int32 blend); + void setDualDestBlend(int32 blend); + + static void enableEffects(Atomic *atomic); }; struct MatFXGlobals @@ -423,6 +454,9 @@ struct Mesh struct MeshHeader { + enum { + TRISTRIP = 1 + }; uint32 flags; uint16 numMeshes; // RW has uint16 serialNum here @@ -445,6 +479,12 @@ struct InstanceDataHeader uint32 platform; }; +struct Triangle +{ + uint16 v[3]; + uint16 matId; +}; + struct Geometry : PluginBase { enum { ID = 8 }; @@ -455,7 +495,7 @@ struct Geometry : PluginBase int32 numMorphTargets; int32 numTexCoordSets; - uint16 *triangles; + Triangle *triangles; uint8 *colors; float32 *texCoords[8]; @@ -481,6 +521,7 @@ struct Geometry : PluginBase bool32 hasColoredMaterial(void); void allocateData(void); void generateTriangles(int8 *adc = NULL); + void buildMeshes(void); enum Flags { @@ -515,6 +556,7 @@ struct Skin void init(int32 numBones, int32 numUsedBones, int32 numVertices); void findNumWeights(int32 numVertices); void findUsedBones(int32 numVertices); + static void setPipeline(Atomic *a, int32 type); }; struct SkinGlobals @@ -769,6 +811,11 @@ struct UVAnimDictionary extern UVAnimDictionary *currentUVAnimDictionary; +struct UVAnim +{ + AnimInterpolator *interp[8]; +}; + extern int32 uvAnimOffset; void registerUVAnimPlugin(void); diff --git a/src/rwps2.h b/src/rwps2.h index 961823f..2659a9b 100644 --- a/src/rwps2.h +++ b/src/rwps2.h @@ -172,13 +172,13 @@ void registerPDSPlugin(int32 n); struct Ps2Raster : NativeRaster { - uint32 tex0[2]; - uint32 tex1[2]; - uint32 miptbp1[2]; - uint32 miptbp2[2]; - uint32 texelSize; - uint32 paletteSize; - uint32 gsSize; + uint32 tex0[2]; + uint32 tex1[2]; + uint32 miptbp1[2]; + uint32 miptbp2[2]; + uint32 texelSize; + uint32 paletteSize; + uint32 gsSize; int8 flags; uint8 *data; //tmp diff --git a/tools/insttest/insttest.cpp b/tools/insttest/insttest.cpp index 93b99e8..28944d1 100644 --- a/tools/insttest/insttest.cpp +++ b/tools/insttest/insttest.cpp @@ -36,6 +36,42 @@ usage(void) exit(1); } +void +dumpUVAnim(Animation *anim) +{ + UVAnimCustomData *cust = (UVAnimCustomData*)anim->customData; + printf(" %s", cust->name); + for(int i = 0; i < 8; i++) + printf(" %d", cust->nodeToUVChannel[i]); + printf("\n %d %x\n", anim->numFrames, anim->interpInfo->id); + UVAnimKeyFrame *kf = (UVAnimKeyFrame*)anim->keyframes; + for(int i = 0; i < anim->numFrames; i++){ + printf(" %f\n", kf->time); + printf(" %f %f %f %f %f %f\n", kf->uv[0], kf->uv[1], kf->uv[2], kf->uv[3], kf->uv[4], kf->uv[5]); + kf++; + } +} + +void +dumpFrameHier(Frame *frame, int ind = 0) +{ + for(int i = 0; i < ind; i++) + printf(" "); + char *name = gta::getNodeName(frame); + HAnimData *hanim = HAnimData::get(frame); + printf("*%s %d %d %s\n", name[0] ? name : "---", frame->objectList.count(), hanim->id, hanim->hierarchy ? "HIERARCHY" : ""); + if(hanim->hierarchy){ + HAnimHierarchy *h = hanim->hierarchy; + for(int i = 0; i < h->numNodes; i++){ + name = h->nodeInfo[i].frame ? gta::getNodeName(h->nodeInfo[i].frame) : ""; + printf("\t\t%d %d\t%p %s\n", h->nodeInfo[i].id, h->nodeInfo[i].flags, h->nodeInfo[i].frame, name); + } + } + for(Frame *child = frame->child; + child; child = child->next) + dumpFrameHier(child, ind+1); +} + int main(int argc, char *argv[]) { @@ -106,7 +142,10 @@ main(int argc, char *argv[]) currentUVAnimDictionary = dict; readChunkHeaderInfo(&in, &header); } - assert(header.type == ID_CLUMP); + if(header.type != ID_CLUMP){ + in.close(); + return 0; + } debugFile = argv[0]; c = Clump::streamRead(&in); assert(c != NULL); @@ -132,6 +171,19 @@ main(int argc, char *argv[]) // printf("%d %f %f %f\n", l->getType(), l->color.red, l->color.green, l->color.blue); //} + HAnimHierarchy *hier = HAnimHierarchy::find(c->getFrame()); + if(hier) + hier->attach(); + dumpFrameHier(c->getFrame()); + + //if(currentUVAnimDictionary){ + // FORLIST(lnk, currentUVAnimDictionary->animations){ + // UVAnimDictEntry *de = UVAnimDictEntry::fromDict(lnk); + // Animation *anim = de->anim; + // dumpUVAnim(anim); + // } + //} + int32 platform = findPlatform(c); if(platform){ rw::platform = platform; @@ -192,10 +244,10 @@ main(int argc, char *argv[]) // out.close(); // delete[] data; + c->destroy(); if(currentUVAnimDictionary) currentUVAnimDictionary->destroy(); - //currentTexDictionary->destroy(); - c->destroy(); + currentTexDictionary->destroy(); return 0; } diff --git a/tools/insttest/insttest.vcxproj b/tools/insttest/insttest.vcxproj index 973bd0f..2f7fa4a 100644 --- a/tools/insttest/insttest.vcxproj +++ b/tools/insttest/insttest.vcxproj @@ -113,7 +113,7 @@ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir) - $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration) + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)$(Platform)\$(Configuration) @@ -202,6 +202,9 @@ true librw.lib;%(AdditionalDependencies) + + copy /y "$(TargetPath)" "C:\Users\aap\bin\" + diff --git a/tools/rsltest/rsltest.cpp b/tools/rsltest/rsltest.cpp index 538a221..5a34b09 100644 --- a/tools/rsltest/rsltest.cpp +++ b/tools/rsltest/rsltest.cpp @@ -13,6 +13,7 @@ using namespace rw; #include "rsl.h" char *argv0; +int32 atmOffset; void RslStream::relocate(void) @@ -68,6 +69,33 @@ mapID(int32 id) return id; } +static RslFrame* +findFrame(RslFrame *f, int32 id) +{ + if(f == NULL) return NULL; + if((f->nodeId & 0xFF) == (id & 0xFF)) + return f; + RslFrame *ff = findFrame(f->next, id); + if(ff) return ff; + return findFrame(f->child, id); +} + +static RslFrame* +findChild(RslFrame *f) +{ + for(RslFrame *c = f->child; c; c = c->next) + if(c->nodeId < 0) + return c; + return NULL; +} + +int32 nextId; + +struct Node { + int32 id; + int32 parent; +}; + Frame* convertFrame(RslFrame *f) { @@ -91,20 +119,46 @@ convertFrame(RslFrame *f) HAnimData *hanim = PLUGINOFFSET(HAnimData, rwf, hAnimOffset); hanim->id = f->nodeId; if(f->hier){ - HAnimHierarchy *hier; - hanim->hierarchy = hier = new HAnimHierarchy; - hier->numNodes = f->hier->numNodes; - hier->flags = f->hier->flags; - hier->maxInterpKeyFrameSize = f->hier->maxKeyFrameSize; - hier->parentFrame = rwf; - hier->parentHierarchy = hier; - hier->nodeInfo = new HAnimNodeInfo[hier->numNodes]; - for(int32 i = 0; i < hier->numNodes; i++){ - hier->nodeInfo[i].id = mapID((uint8)f->hier->pNodeInfo[i].id); - hier->nodeInfo[i].index = f->hier->pNodeInfo[i].index; - hier->nodeInfo[i].flags = f->hier->pNodeInfo[i].flags; - hier->nodeInfo[i].frame = NULL; + int32 numNodes = f->hier->numNodes; + int32 *nodeFlags = new int32[numNodes]; + int32 *nodeIDs = new int32[numNodes]; + + nextId = 2000; + Node *nodehier = new Node[numNodes]; + int32 stack[100]; + int32 sp = 0; + stack[sp] = -1; + // Match up nodes with frames to fix and assign IDs + // NOTE: assignment can only work reliably when not more + // than one child node needs an ID + for(int32 i = 0; i < numNodes; i++){ + RslHAnimNodeInfo *ni = &f->hier->pNodeInfo[i]; + Node *n = &nodehier[i]; + n->parent = stack[sp]; + if(ni->flags & HAnimHierarchy::PUSH) + sp++; + stack[sp] = i; + RslFrame *ff = findFrame(f, (uint8)ni->id); + n->id = ff->nodeId; + if(n->id < 0){ + ff = findFrame(f, nodehier[n->parent].id); + ff = findChild(ff); + n->id = ff->nodeId = nextId++; + } + //printf("%d %s %d %d\n", i, ff->name, n->id, n->parent); + if(ni->flags & HAnimHierarchy::POP) + sp--; + + nodeFlags[i] = ni->flags; + nodeIDs[i] = n->id; } + + HAnimHierarchy *hier = HAnimHierarchy::create(numNodes, nodeFlags, nodeIDs, f->hier->flags, f->hier->maxKeyFrameSize); + hanim->hierarchy = hier; + + delete[] nodeFlags; + delete[] nodeIDs; + delete[] nodehier; } return rwf; } @@ -302,6 +356,8 @@ convertAtomic(RslAtomic *atomic) Geometry *rwg = Geometry::create(0, 0, 0); rwa->geometry = rwg; + *PLUGINOFFSET(RslAtomic*, rwa, atmOffset) = atomic; + rwg->numMaterials = g->matList.numMaterials; rwg->materialList = new Material*[rwg->numMaterials]; for(int32 i = 0; i < rwg->numMaterials; i++) @@ -447,6 +503,41 @@ makeTextures(RslAtomic *atomic, void*) return atomic; } +void +moveAtomics(Frame *f) +{ + static char *names[] = { "", "hi_ok", "hi_dam" }; + if(f == NULL) return; + int n = f->objectList.count(); + if(n > 1){ + char *oldname = gta::getNodeName(f); + ObjectWithFrame **objs = new ObjectWithFrame*[n]; + int i = 0; + FORLIST(lnk, f->objectList){ + ObjectWithFrame *obj = ObjectWithFrame::fromFrame(lnk); + assert(obj->type == Atomic::ID); + objs[i] = obj; + obj->setFrame(NULL); + i++; + } + for(i = 0; i < n; i++){ + Frame *ff = Frame::create(); + RslAtomic *rsla = *PLUGINOFFSET(RslAtomic*, objs[i], atmOffset); + char *name = gta::getNodeName(ff); + strncpy(name, oldname, 24); + char *end = strrchr(name, '_'); + if(end){ + *(++end) = '\0'; + strcat(end, names[rsla->unk3&3]); + } + f->addChild(ff); + objs[i]->setFrame(ff); + } + delete[] objs; + } + moveAtomics(f->next); + moveAtomics(f->child); +} @@ -751,6 +842,7 @@ usage(void) fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n"); fprintf(stderr, "\t-x extract textures to tga\n"); fprintf(stderr, "\t-s don't unswizzle textures\n"); + fprintf(stderr, "\t-a fix Atomics placement inside hierarchy (mdl files)\n"); exit(1); } @@ -758,11 +850,13 @@ int main(int argc, char *argv[]) { gta::attachPlugins(); + atmOffset = Atomic::registerPlugin(sizeof(void*), 0x1000000, NULL, NULL, NULL); rw::version = 0x34003; rw::platform = PLATFORM_D3D8; assert(sizeof(void*) == 4); int extract = 0; + int fixAtomics = 0; ARGBEGIN{ case 'v': @@ -774,6 +868,9 @@ main(int argc, char *argv[]) case 'x': extract++; break; + case 'a': + fixAtomics++; + break; default: usage(); }ARGEND; @@ -906,6 +1003,8 @@ main(int argc, char *argv[]) } writeDff: rwc = convertClump(clump); + if(fixAtomics) + moveAtomics(rwc->getFrame()); if(argc > 1) assert(stream.open(argv[1], "wb")); else