From e1bb20c800fedfb587684df8a4ea61b93254f083 Mon Sep 17 00:00:00 2001 From: Angelo Papenhoff Date: Fri, 9 Jan 2015 20:17:32 +0100 Subject: [PATCH] Implemented MatFX. --- dffwrite.cpp | 5 + src/clump.cpp | 34 ++++- src/geometry.cpp | 26 +++- src/geometryplg.cpp | 333 +++++++++++++++++++++++++++++++++++++++++++- src/rwbase.cpp | 1 + src/rwbase.h | 4 + src/rwobjects.h | 109 +++++++++++---- src/rwplugin.h | 3 +- 8 files changed, 481 insertions(+), 34 deletions(-) diff --git a/dffwrite.cpp b/dffwrite.cpp index 9e689fa..49d28ca 100644 --- a/dffwrite.cpp +++ b/dffwrite.cpp @@ -18,6 +18,9 @@ main(int argc, char *argv[]) // Rw::Version = 0x33002; + Rw::RegisterMaterialRightsPlugin(); + Rw::RegisterMatFXPlugin(); + Rw::RegisterAtomicRightsPlugin(); Rw::RegisterNodeNamePlugin(); Rw::RegisterBreakableModelPlugin(); Rw::RegisterExtraVertColorPlugin(); @@ -26,6 +29,7 @@ main(int argc, char *argv[]) Rw::RegisterNativeDataPlugin(); // Rw::Ps2::RegisterNativeDataPlugin(); Rw::RegisterMeshPlugin(); + Rw::Clump *c; // ifstream in(argv[1], ios::binary); @@ -45,6 +49,7 @@ main(int argc, char *argv[]) in.open(data, len); Rw::FindChunk(&in, Rw::ID_CLUMP, NULL, NULL); + Rw::DebugFile = argv[1]; c = Rw::Clump::streamRead(&in); assert(c != NULL); diff --git a/src/clump.cpp b/src/clump.cpp index b18267b..32d6be8 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -117,7 +117,9 @@ makeFrameList(Frame *frame, Frame **flist) return flist; } - +// +// Clump +// Clump::Clump(void) { @@ -367,6 +369,9 @@ Clump::frameListStreamWrite(Stream *stream, Frame **frameList, int32 numFrames) frameList[i]->streamWritePlugins(stream); } +// +// Atomic +// Atomic::Atomic(void) { @@ -430,6 +435,33 @@ Atomic::streamGetSize(void) return 12 + 16 + 12 + this->streamGetPluginSize(); } +// Atomic Rights plugin + +static void +readAtomicRights(Stream *stream, int32, void *, int32, int32) +{ + uint32 buffer[2]; + uint32 version; +stream->seek(-4); +version = stream->readU32(); + stream->read(buffer, 8); +// printf("atomicrights: %s %X %X %X\n", DebugFile, LibraryIDUnpackVersion(version), buffer[0], buffer[1]); + printf("atomicrights: %X %X %X\n", LibraryIDUnpackVersion(version), buffer[0], buffer[1]); +} + +void +RegisterAtomicRightsPlugin(void) +{ + Atomic::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL); + Atomic::registerPluginStream(ID_RIGHTTORENDER, + (StreamRead)readAtomicRights, + NULL, NULL); +} + + +// +// Light +// Light::Light(void) { diff --git a/src/geometry.cpp b/src/geometry.cpp index c3387a0..8aba1e9 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -269,7 +269,9 @@ Geometry::addMorphTargets(int32 n) } - +// +// Material +// Material::Material(void) { @@ -383,7 +385,29 @@ Material::streamGetSize(void) return size; } +// Material Rights plugin +static void +readMaterialRights(Stream *stream, int32, void *, int32, int32) +{ + uint32 buffer[2]; + stream->read(buffer, 8); + printf("materialrights: %X %X\n", buffer[0], buffer[1]); +} + +void +RegisterMaterialRightsPlugin(void) +{ + Material::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL); + Material::registerPluginStream(ID_RIGHTTORENDER, + (StreamRead)readMaterialRights, + NULL, NULL); +} + + +// +// Texture +// Texture::Texture(void) { diff --git a/src/geometryplg.cpp b/src/geometryplg.cpp index 28fa01f..7261cab 100644 --- a/src/geometryplg.cpp +++ b/src/geometryplg.cpp @@ -229,12 +229,12 @@ destroySkin(void *object, int32 offset, int32) static void* copySkin(void *dst, void *src, int32 offset, int32) { - Geometry *geometry = (Geometry*)src; - assert(geometry->instData == NULL); - assert(((Geometry*)src)->numVertices == ((Geometry*)dst)->numVertices); Skin *srcskin = *PLUGINOFFSET(Skin*, src, offset); if(srcskin == NULL) return dst; + Geometry *geometry = (Geometry*)src; + assert(geometry->instData == NULL); + assert(((Geometry*)src)->numVertices == ((Geometry*)dst)->numVertices); Skin *dstskin = new Skin; *PLUGINOFFSET(Skin*, dst, offset) = dstskin; dstskin->numBones = srcskin->numBones; @@ -413,9 +413,330 @@ RegisterSkinPlugin(void) Geometry::registerPlugin(sizeof(Skin*), ID_SKIN, createSkin, destroySkin, copySkin); Geometry::registerPluginStream(ID_SKIN, - (StreamRead)readSkin, - (StreamWrite)writeSkin, - (StreamGetSize)getSizeSkin); + readSkin, writeSkin, getSizeSkin); +} + +// Atomic MatFX + +static void* +createAtomicMatFX(void *object, int32 offset, int32) +{ + *PLUGINOFFSET(int32, object, offset) = 0; + return object; +} + +static void* +copyAtomicMatFX(void *dst, void *src, int32 offset, int32) +{ + *PLUGINOFFSET(int32, dst, offset) = *PLUGINOFFSET(int32, src, offset); + return dst; +} + +static void +readAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32) +{ + int32 flag; +// uint32 version; +//stream->seek(-4); +//version = stream->readU32(); + stream->read(&flag, 4); +//printf("atomicMatFX: %X %X\n", LibraryIDUnpackVersion(version), flag); + *PLUGINOFFSET(int32, object, offset) = flag; + // TODO: set Pipeline +} + +static void +writeAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32) +{ + int32 flag; + flag = *PLUGINOFFSET(int32, object, offset); + stream->writeI32(flag); +} + +static int32 +getSizeAtomicMatFX(void *object, int32 offset, int32) +{ + int32 flag; + flag = *PLUGINOFFSET(int32, object, offset); + return flag ? 4 : -1; +} + +// Material MatFX + +// TODO: Frames and Matrices? +static void +clearMatFX(MatFX *matfx) +{ + for(int i = 0; i < 2; i++) + switch(matfx->fx[i].type){ + case MatFX::BUMPMAP: + if(matfx->fx[i].bump.bumpedTex) + matfx->fx[i].bump.bumpedTex->decRef(); + if(matfx->fx[i].bump.tex) + matfx->fx[i].bump.tex->decRef(); + break; + + case MatFX::ENVMAP: + if(matfx->fx[i].env.tex) + matfx->fx[i].env.tex->decRef(); + break; + + case MatFX::DUAL: + if(matfx->fx[i].dual.tex) + matfx->fx[i].dual.tex->decRef(); + break; + } + memset(matfx, 0, sizeof(MatFX)); +} + +void +MatFX::setEffects(uint32 flags) +{ + if(this->flags != 0 && this->flags != flags) + clearMatFX(this); + this->flags = flags; + switch(flags){ + case BUMPMAP: + case ENVMAP: + case DUAL: + case UVTRANSFORM: + this->fx[0].type = flags; + this->fx[1].type = NOTHING; + break; + + case BUMPENVMAP: + this->fx[0].type = BUMPMAP; + this->fx[1].type = ENVMAP; + break; + + case DUALUVTRANSFORM: + this->fx[0].type = UVTRANSFORM; + this->fx[1].type = DUAL; + break; + } +} + +int32 +MatFX::getEffectIndex(uint32 type) +{ + for(int i = 0; i < 2; i++) + if(this->fx[i].type == type) + return i; + return -1; +} + +static void* +createMaterialMatFX(void *object, int32 offset, int32) +{ + *PLUGINOFFSET(MatFX*, object, offset) = NULL; + return object; +} + +static void* +destroyMaterialMatFX(void *object, int32 offset, int32) +{ + MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset); + if(matfx){ + clearMatFX(matfx); + delete matfx; + } + return object; +} + +static void* +copyMaterialMatFX(void *dst, void *src, int32 offset, int32) +{ + MatFX *srcfx = *PLUGINOFFSET(MatFX*, src, offset); + if(srcfx == NULL) + return dst; + MatFX *dstfx = new MatFX; + *PLUGINOFFSET(MatFX*, dst, offset) = dstfx; + memcpy(dstfx, srcfx, sizeof(MatFX)); + for(int i = 0; i < 2; i++) + switch(dstfx->fx[i].type){ + case MatFX::BUMPMAP: + if(dstfx->fx[i].bump.bumpedTex) + dstfx->fx[i].bump.bumpedTex->refCount++; + if(dstfx->fx[i].bump.tex) + dstfx->fx[i].bump.tex->refCount++; + break; + + case MatFX::ENVMAP: + if(dstfx->fx[i].env.tex) + dstfx->fx[i].env.tex->refCount++; + break; + + case MatFX::DUAL: + if(dstfx->fx[i].dual.tex) + dstfx->fx[i].dual.tex->refCount++; + break; + } + return dst; +} + +static void +readMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32) +{ + Texture *tex, *bumpedTex; + float coefficient; + int32 fbAlpha; + int32 srcBlend, dstBlend; + int32 idx; + + MatFX *matfx = new MatFX; + memset(matfx, 0, sizeof(MatFX)); + *PLUGINOFFSET(MatFX*, object, offset) = matfx; + matfx->setEffects(stream->readU32()); + + for(int i = 0; i < 2; i++){ + uint32 type = stream->readU32(); + switch(type){ + case MatFX::BUMPMAP: + coefficient = stream->readF32(); + bumpedTex = tex = NULL; + if(stream->readI32()){ + assert(FindChunk(stream, ID_TEXTURE, + NULL, NULL)); + bumpedTex = Texture::streamRead(stream); + } + if(stream->readI32()){ + assert(FindChunk(stream, ID_TEXTURE, + NULL, NULL)); + tex = Texture::streamRead(stream); + } + idx = matfx->getEffectIndex(type); + assert(idx >= 0); + matfx->fx[idx].bump.bumpedTex = bumpedTex; + matfx->fx[idx].bump.tex = tex; + matfx->fx[idx].bump.coefficient = coefficient; + break; + + case MatFX::ENVMAP: + coefficient = stream->readF32(); + fbAlpha = stream->readI32(); + tex = NULL; + if(stream->readI32()){ + assert(FindChunk(stream, ID_TEXTURE, + NULL, NULL)); + tex = Texture::streamRead(stream); + } + idx = matfx->getEffectIndex(type); + assert(idx >= 0); + matfx->fx[idx].env.tex = tex; + matfx->fx[idx].env.fbAlpha = fbAlpha; + matfx->fx[idx].env.coefficient = coefficient; + break; + + case MatFX::DUAL: + srcBlend = stream->readI32(); + dstBlend = stream->readI32(); + tex = NULL; + if(stream->readI32()){ + assert(FindChunk(stream, ID_TEXTURE, + NULL, NULL)); + tex = Texture::streamRead(stream); + } + idx = matfx->getEffectIndex(type); + assert(idx >= 0); + matfx->fx[idx].dual.tex = tex; + matfx->fx[idx].dual.srcBlend = srcBlend; + matfx->fx[idx].dual.dstBlend = dstBlend; + break; + } + } +} + +static void +writeMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32) +{ + MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset); + + stream->writeU32(matfx->flags); + for(int i = 0; i < 2; i++){ + stream->writeU32(matfx->fx[i].type); + switch(matfx->fx[i].type){ + case MatFX::BUMPMAP: + stream->writeF32(matfx->fx[i].bump.coefficient); + stream->writeI32(matfx->fx[i].bump.bumpedTex != NULL); + if(matfx->fx[i].bump.bumpedTex) + matfx->fx[i].bump.bumpedTex->streamWrite(stream); + stream->writeI32(matfx->fx[i].bump.tex != NULL); + if(matfx->fx[i].bump.tex) + matfx->fx[i].bump.tex->streamWrite(stream); + break; + + case MatFX::ENVMAP: + stream->writeF32(matfx->fx[i].env.coefficient); + stream->writeI32(matfx->fx[i].env.fbAlpha); + stream->writeI32(matfx->fx[i].env.tex != NULL); + if(matfx->fx[i].env.tex) + matfx->fx[i].env.tex->streamWrite(stream); + break; + + case MatFX::DUAL: + stream->writeI32(matfx->fx[i].dual.srcBlend); + stream->writeI32(matfx->fx[i].dual.dstBlend); + stream->writeI32(matfx->fx[i].dual.tex != NULL); + if(matfx->fx[i].dual.tex) + matfx->fx[i].dual.tex->streamWrite(stream); + break; + } + } +} + +static int32 +getSizeMaterialMatFX(void *object, int32 offset, int32) +{ + MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset); + if(matfx == NULL) + return -1; + int32 size = 4 + 4 + 4; + + for(int i = 0; i < 2; i++) + switch(matfx->fx[i].type){ + case MatFX::BUMPMAP: + size += 4 + 4 + 4; + if(matfx->fx[i].bump.bumpedTex) + size += 12 + + matfx->fx[i].bump.bumpedTex->streamGetSize(); + if(matfx->fx[i].bump.tex) + size += 12 + + matfx->fx[i].bump.tex->streamGetSize(); + break; + + case MatFX::ENVMAP: + size += 4 + 4 + 4; + if(matfx->fx[i].env.tex) + size += 12 + + matfx->fx[i].env.tex->streamGetSize(); + break; + + case MatFX::DUAL: + size += 4 + 4 + 4; + if(matfx->fx[i].dual.tex) + size += 12 + + matfx->fx[i].dual.tex->streamGetSize(); + break; + } + return size; +} + +void +RegisterMatFXPlugin(void) +{ + Atomic::registerPlugin(sizeof(int32), ID_MATFX, + createAtomicMatFX, NULL, copyAtomicMatFX); + Atomic::registerPluginStream(ID_MATFX, + readAtomicMatFX, + writeAtomicMatFX, + getSizeAtomicMatFX); + Material::registerPlugin(sizeof(MatFX*), ID_MATFX, + createMaterialMatFX, destroyMaterialMatFX, + copyMaterialMatFX); + Material::registerPluginStream(ID_MATFX, + readMaterialMatFX, + writeMaterialMatFX, + getSizeMaterialMatFX); } } diff --git a/src/rwbase.cpp b/src/rwbase.cpp index ee19fb4..9520e35 100644 --- a/src/rwbase.cpp +++ b/src/rwbase.cpp @@ -14,6 +14,7 @@ namespace Rw { int Version = 0x36003; int Build = 0xFFFF; +char *DebugFile = NULL; int32 Stream::writeI8(int8 val) diff --git a/src/rwbase.h b/src/rwbase.h index 21fa2e2..175e72d 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -110,12 +110,16 @@ enum PluginID ID_UVANIMDICT = 0x2B, ID_SKIN = 0x116, + ID_MATFX = 0x120, + ID_PDS = 0x131, ID_ADC = 0x134, + ID_MESH = 0x50E, ID_NATIVEDATA = 0x510, }; extern int Version; extern int Build; +extern char *DebugFile; inline uint32 LibraryIDPack(int version, int build) diff --git a/src/rwobjects.h b/src/rwobjects.h index 374ab0c..74c8b73 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -1,5 +1,12 @@ namespace Rw { +// TODO: mostly +struct Pipeline +{ + uint32 pluginID; + uint32 pluginData; +}; + struct Object { uint8 type; @@ -8,6 +15,28 @@ struct Object void *parent; }; +struct Frame : PluginBase, Object +{ + typedef Frame *(*Callback)(Frame *f, void *data); + float32 matrix[16]; + float32 ltm[16]; + + Frame *child; + Frame *next; + Frame *root; + + // temporary + int32 matflag; + + Frame(void); + Frame(Frame *f); + ~Frame(void); + Frame *addChild(Frame *f); + Frame *removeChild(void); + Frame *forAllChildren(Callback cb, void *data); + int32 count(void); +}; + struct Image { int32 flags; @@ -74,6 +103,56 @@ struct Material : PluginBase uint32 streamGetSize(void); }; +struct MatFX +{ + enum Flags { + NOTHING = 0, + BUMPMAP, + ENVMAP, + BUMPENVMAP, + DUAL, + UVTRANSFORM, + DUALUVTRANSFORM + }; + struct Bump { + Frame *frame; + Texture *bumpedTex; + Texture *tex; + float coefficient; + }; + struct Env { + Frame *frame; + Texture *tex; + float coefficient; + int32 fbAlpha; + }; + struct Dual { + Texture *tex; + int32 srcBlend; + int32 dstBlend; + }; + struct UVtransform { + float *baseTransform; + float *dualTransform; + }; + struct { + uint32 type; + union { + Bump bump; + Env env; + Dual dual; + UVtransform uvtransform; + }; + } fx[2]; + uint32 flags; + + void setEffects(uint32 flags); + int32 getEffectIndex(uint32 type); +}; + +void RegisterMaterialRightsPlugin(void); +void RegisterMatFXPlugin(void); + struct Mesh { uint16 *indices; @@ -160,27 +239,9 @@ struct Skin uint8 *data; // only used by delete }; -struct Frame : PluginBase, Object -{ - typedef Frame *(*Callback)(Frame *f, void *data); - float32 matrix[16]; - float32 ltm[16]; - - Frame *child; - Frame *next; - Frame *root; - - // temporary - int32 matflag; - - Frame(void); - Frame(Frame *f); - ~Frame(void); - Frame *addChild(Frame *f); - Frame *removeChild(void); - Frame *forAllChildren(Callback cb, void *data); - int32 count(void); -}; +void RegisterMeshPlugin(void); +void RegisterNativeDataPlugin(void); +void RegisterSkinPlugin(void); struct Clump; @@ -216,6 +277,8 @@ struct Atomic : PluginBase, Object uint32 streamGetSize(void); }; +void RegisterAtomicRightsPlugin(void); + struct Clump : PluginBase, Object { int32 numAtomics; @@ -237,8 +300,4 @@ private: void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf); }; -void RegisterMeshPlugin(void); -void RegisterNativeDataPlugin(void); -void RegisterSkinPlugin(void); - } diff --git a/src/rwplugin.h b/src/rwplugin.h index 1605f94..f91e4a7 100644 --- a/src/rwplugin.h +++ b/src/rwplugin.h @@ -105,7 +105,8 @@ PluginBase::streamWritePlugins(Stream *stream) int size = this->streamGetPluginSize(); Rw::WriteChunkHeader(stream, Rw::ID_EXTENSION, size); for(Plugin *p = this->s_plugins; p; p = p->next){ - if((size = p->getSize(this, p->offset, p->size)) < 0) + if(p->getSize == NULL || + (size = p->getSize(this, p->offset, p->size)) < 0) continue; Rw::WriteChunkHeader(stream, p->id, size); p->write(stream, size, this, p->offset, p->size);