diff --git a/Makefile b/Makefile index 80be921..a79e6e7 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,9 @@ SRC := $(wildcard $(SRCDIR)/*.cpp $(SRCDIR)/*/*.cpp) OBJ := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.o,$(SRC)) DEP := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.d,$(SRC)) INC := -I/usr/local/include -CFLAGS=-Wall -Wextra -g $(BUILDDEF) -Wno-parentheses -Wno-invalid-offsetof -fno-diagnostics-show-caret -Wno-unused-parameter - #-Wconversion +CFLAGS=-Wall -Wextra -g $(BUILDDEF) -fno-diagnostics-show-caret \ + -Wno-parentheses -Wno-invalid-offsetof \ + -Wno-unused-parameter -Wno-sign-compare LIB=librw-$(BUILD).a $(LIB): $(OBJ) diff --git a/src/camera.cpp b/src/camera.cpp index b1e78b8..be366cd 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -17,13 +17,13 @@ defaultBeginUpdateCB(Camera *cam) { engine->currentCamera = cam; Frame::syncDirty(); - DRIVER.beginUpdate(cam); + DRIVER->beginUpdate(cam); } void defaultEndUpdateCB(Camera *cam) { - DRIVER.endUpdate(cam); + DRIVER->endUpdate(cam); } static void diff --git a/src/clump.cpp b/src/clump.cpp index 57a4a6a..be7936f 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -511,7 +511,7 @@ Atomic::getPipeline(void) { return this->pipeline ? this->pipeline : - driver[platform].defaultPipeline; + driver[platform]->defaultPipeline; } void diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index c9fd3aa..0b4f1a7 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -348,7 +348,7 @@ deleteObject(void *object) int32 nativeRasterOffset; -static void +void rasterCreate(Raster *raster) { D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); @@ -392,21 +392,21 @@ rasterCreate(Raster *raster) format); } -static uint8* +uint8* rasterLock(Raster *raster, int32 level) { D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); return lockTexture(natras->texture, level); } -static void +void rasterUnlock(Raster *raster, int32 level) { D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); unlockTexture(natras->texture, level); } -static int32 +int32 rasterNumLevels(Raster *raster) { D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); @@ -419,7 +419,7 @@ rasterNumLevels(Raster *raster) #endif } -static void +void rasterFromImage(Raster *raster, Image *image) { int32 format; @@ -586,34 +586,9 @@ copyNativeRaster(void *dst, void *, int32 offset, int32) return dst; } -static void* -nativeOpen(void*, int32, int32) -{ - driver[PLATFORM_D3D8].rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_D3D8].rasterCreate = rasterCreate; - driver[PLATFORM_D3D8].rasterLock = rasterLock; - driver[PLATFORM_D3D8].rasterUnlock = rasterUnlock; - driver[PLATFORM_D3D8].rasterNumLevels = rasterNumLevels; - driver[PLATFORM_D3D8].rasterFromImage = rasterFromImage; - - driver[PLATFORM_D3D9].rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_D3D9].rasterCreate = rasterCreate; - driver[PLATFORM_D3D9].rasterLock = rasterLock; - driver[PLATFORM_D3D9].rasterUnlock = rasterUnlock; - driver[PLATFORM_D3D9].rasterNumLevels = rasterNumLevels; - driver[PLATFORM_D3D9].rasterFromImage = rasterFromImage; -} - -static void* -nativeClose(void*, int32, int32) -{ - printf("d3d native close\n"); -} - void registerNativeRaster(void) { - Engine::registerPlugin(0, ID_RASTERD3D9, nativeOpen, nativeClose); nativeRasterOffset = Raster::registerPlugin(sizeof(D3dRaster), ID_RASTERD3D9, createNativeRaster, diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index 6fe693c..1637993 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -12,18 +12,43 @@ #include "rwd3d.h" #include "rwd3d8.h" +#include "rwd3dimpl.h" + #define PLUGIN_ID 2 namespace rw { namespace d3d8 { using namespace d3d; +void* +driverOpen(void *o, int32, int32) +{ + printf("d3d8 open\n"); + driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline(); + + driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset; + driver[PLATFORM_D3D8]->rasterCreate = rasterCreate; + driver[PLATFORM_D3D8]->rasterLock = rasterLock; + driver[PLATFORM_D3D8]->rasterUnlock = rasterUnlock; + driver[PLATFORM_D3D8]->rasterNumLevels = rasterNumLevels; + driver[PLATFORM_D3D8]->rasterFromImage = rasterFromImage; + return o; +} + +void* +driverClose(void *o, int32, int32) +{ + return o; +} + void initializePlatform(void) { + Driver::registerPlugin(PLATFORM_D3D8, 0, PLATFORM_D3D8, + driverOpen, driverClose); + // shared between D3D8 and 9 if(nativeRasterOffset == 0) registerNativeRaster(); - driver[PLATFORM_D3D8].defaultPipeline = makeDefaultPipeline(); } uint32 @@ -401,30 +426,6 @@ makeDefaultPipeline(void) return pipe; } -ObjPipeline* -makeSkinPipeline(void) -{ - ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); - pipe->instanceCB = defaultInstanceCB; - pipe->uninstanceCB = defaultUninstanceCB; - pipe->renderCB = defaultRenderCB; - pipe->pluginID = ID_SKIN; - pipe->pluginData = 1; - return pipe; -} - -ObjPipeline* -makeMatFXPipeline(void) -{ - ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); - pipe->instanceCB = defaultInstanceCB; - pipe->uninstanceCB = defaultUninstanceCB; - pipe->renderCB = defaultRenderCB; - pipe->pluginID = ID_MATFX; - pipe->pluginData = 0; - return pipe; -} - // Native Texture and Raster // only handles 4 and 8 bit textures right now diff --git a/src/d3d/d3d8plugins.cpp b/src/d3d/d3d8plugins.cpp new file mode 100644 index 0000000..49dd37c --- /dev/null +++ b/src/d3d/d3d8plugins.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwplugins.h" +#include "rwd3d.h" +#include "rwd3d8.h" + +namespace rw { +namespace d3d8 { +using namespace d3d; + +// Skin + +static void* +skinOpen(void *o, int32, int32) +{ + skinGlobals.pipelines[PLATFORM_D3D8] = makeSkinPipeline(); + return o; +} + +static void* +skinClose(void *o, int32, int32) +{ + return o; +} + +void +initSkin(void) +{ + Driver::registerPlugin(PLATFORM_D3D8, 0, ID_SKIN, + skinOpen, skinClose); +} + +ObjPipeline* +makeSkinPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; + pipe->pluginID = ID_SKIN; + pipe->pluginData = 1; + return pipe; +} + +// MatFX + +static void* +matfxOpen(void *o, int32, int32) +{ + matFXGlobals.pipelines[PLATFORM_D3D8] = makeMatFXPipeline(); + return o; +} + +static void* +matfxClose(void *o, int32, int32) +{ + return o; +} + +void +initMatFX(void) +{ + Driver::registerPlugin(PLATFORM_D3D8, 0, ID_MATFX, + matfxOpen, matfxClose); +} + +ObjPipeline* +makeMatFXPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; + pipe->pluginID = ID_MATFX; + pipe->pluginData = 0; + return pipe; +} + +} +} diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index 717a37d..b4c603c 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -12,6 +12,8 @@ #include "rwd3d.h" #include "rwd3d9.h" +#include "rwd3dimpl.h" + #define PLUGIN_ID 2 namespace rw { @@ -25,12 +27,35 @@ using namespace d3d; #define NUMDECLELT 12 +void* +driverOpen(void *o, int32, int32) +{ + printf("d3d9 open\n"); + driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline(); + + driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset; + driver[PLATFORM_D3D9]->rasterCreate = rasterCreate; + driver[PLATFORM_D3D9]->rasterLock = rasterLock; + driver[PLATFORM_D3D9]->rasterUnlock = rasterUnlock; + driver[PLATFORM_D3D9]->rasterNumLevels = rasterNumLevels; + driver[PLATFORM_D3D9]->rasterFromImage = rasterFromImage; + return o; +} + +void* +driverClose(void *o, int32, int32) +{ + return o; +} + void initializePlatform(void) { + Driver::registerPlugin(PLATFORM_D3D9, 0, PLATFORM_D3D9, + driverOpen, driverClose); + // shared between D3D8 and 9 if(nativeRasterOffset == 0) registerNativeRaster(); - driver[PLATFORM_D3D9].defaultPipeline = makeDefaultPipeline(); } void* @@ -559,30 +584,6 @@ makeDefaultPipeline(void) return pipe; } -ObjPipeline* -makeSkinPipeline(void) -{ - ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9); - pipe->instanceCB = defaultInstanceCB; - pipe->uninstanceCB = defaultUninstanceCB; - pipe->renderCB = defaultRenderCB; - pipe->pluginID = ID_SKIN; - pipe->pluginData = 1; - return pipe; -} - -ObjPipeline* -makeMatFXPipeline(void) -{ - ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9); - pipe->instanceCB = defaultInstanceCB; - pipe->uninstanceCB = defaultUninstanceCB; - pipe->renderCB = defaultRenderCB; - pipe->pluginID = ID_MATFX; - pipe->pluginData = 0; - return pipe; -} - // Native Texture and Raster Texture* diff --git a/src/d3d/d3d9plugins.cpp b/src/d3d/d3d9plugins.cpp new file mode 100644 index 0000000..f702478 --- /dev/null +++ b/src/d3d/d3d9plugins.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwplugins.h" +#include "rwd3d.h" +#include "rwd3d9.h" + +namespace rw { +namespace d3d9 { +using namespace d3d; + +// Skin + +static void* +skinOpen(void *o, int32, int32) +{ + skinGlobals.pipelines[PLATFORM_D3D9] = makeSkinPipeline(); + return o; +} + +static void* +skinClose(void *o, int32, int32) +{ + return o; +} + +void +initSkin(void) +{ + Driver::registerPlugin(PLATFORM_D3D9, 0, ID_SKIN, + skinOpen, skinClose); +} + +ObjPipeline* +makeSkinPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; + pipe->pluginID = ID_SKIN; + pipe->pluginData = 1; + return pipe; +} + +// MatFX + +static void* +matfxOpen(void *o, int32, int32) +{ + matFXGlobals.pipelines[PLATFORM_D3D9] = makeMatFXPipeline(); + return o; +} + +static void* +matfxClose(void *o, int32, int32) +{ + return o; +} + +void +initMatFX(void) +{ + Driver::registerPlugin(PLATFORM_D3D9, 0, ID_MATFX, + matfxOpen, matfxClose); +} + +ObjPipeline* +makeMatFXPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; + pipe->pluginID = ID_MATFX; + pipe->pluginData = 0; + return pipe; +} + +} +} diff --git a/src/d3d/rwd3d8.h b/src/d3d/rwd3d8.h index d8aac01..6a7de5f 100644 --- a/src/d3d/rwd3d8.h +++ b/src/d3d/rwd3d8.h @@ -47,14 +47,20 @@ public: ObjPipeline(uint32 platform); }; -void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header); -void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header); +void defaultInstanceCB(Geometry *geo, InstanceData *header); +void defaultUninstanceCB(Geometry *geo, InstanceData *header); void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header); ObjPipeline *makeDefaultPipeline(void); +// Skin plugin + +void initSkin(void); ObjPipeline *makeSkinPipeline(void); +// MatFX plugin + +void initMatFX(void); ObjPipeline *makeMatFXPipeline(void); // Native Texture and Raster diff --git a/src/d3d/rwd3d9.h b/src/d3d/rwd3d9.h index a382965..91ebd82 100644 --- a/src/d3d/rwd3d9.h +++ b/src/d3d/rwd3d9.h @@ -76,8 +76,14 @@ void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header); ObjPipeline *makeDefaultPipeline(void); +// Skin plugin + +void initSkin(void); ObjPipeline *makeSkinPipeline(void); +// MatFX plugin + +void initMatFX(void); ObjPipeline *makeMatFXPipeline(void); // Native Texture and Raster diff --git a/src/d3d/rwd3dimpl.h b/src/d3d/rwd3dimpl.h new file mode 100644 index 0000000..9259d81 --- /dev/null +++ b/src/d3d/rwd3dimpl.h @@ -0,0 +1,11 @@ +namespace rw { +namespace d3d { + +void rasterCreate(Raster *raster); +uint8 *rasterLock(Raster *raster, int32 level); +void rasterUnlock(Raster *raster, int32 level); +int32 rasterNumLevels(Raster *raster); +void rasterFromImage(Raster *raster, Image *image); + +} +} diff --git a/src/d3d/rwxbox.h b/src/d3d/rwxbox.h index 1c16af1..6f59c31 100644 --- a/src/d3d/rwxbox.h +++ b/src/d3d/rwxbox.h @@ -46,14 +46,21 @@ public: ObjPipeline *makeDefaultPipeline(void); +void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header); +void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header); + // Skin plugin Stream *readNativeSkin(Stream *stream, int32, void *object, int32 offset); Stream *writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset); int32 getSizeNativeSkin(void *object, int32 offset); +void initSkin(void); ObjPipeline *makeSkinPipeline(void); +// MatFX plugin + +void initMatFX(void); ObjPipeline *makeMatFXPipeline(void); // Vertex Format plugin diff --git a/src/d3d/rwxboximpl.h b/src/d3d/rwxboximpl.h new file mode 100644 index 0000000..8fd891b --- /dev/null +++ b/src/d3d/rwxboximpl.h @@ -0,0 +1,10 @@ +namespace rw { +namespace xbox { + +void rasterCreate(Raster *raster); +uint8 *rasterLock(Raster *raster, int32 level); +void rasterUnlock(Raster*, int32); +int32 rasterNumLevels(Raster *raster); + +} +} diff --git a/src/d3d/xbox.cpp b/src/d3d/xbox.cpp index ff1dad3..760823e 100644 --- a/src/d3d/xbox.cpp +++ b/src/d3d/xbox.cpp @@ -12,16 +12,41 @@ #include "../rwplugins.h" #include "rwxbox.h" +#include "rwxboximpl.h" + #define PLUGIN_ID 2 namespace rw { namespace xbox { +void* +driverOpen(void *o, int32, int32) +{ + printf("xbox open\n"); + driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline(); + + driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset; + driver[PLATFORM_XBOX]->rasterCreate = rasterCreate; + driver[PLATFORM_XBOX]->rasterLock = rasterLock; + driver[PLATFORM_XBOX]->rasterUnlock = rasterUnlock; + driver[PLATFORM_XBOX]->rasterNumLevels = rasterNumLevels; + // TODO: from image + + return o; +} + +void* +driverClose(void *o, int32, int32) +{ + return o; +} + void initializePlatform(void) { + Driver::registerPlugin(PLATFORM_XBOX, 0, PLATFORM_XBOX, + driverOpen, driverClose); registerNativeRaster(); - driver[PLATFORM_XBOX].defaultPipeline = makeDefaultPipeline(); } void* @@ -352,322 +377,6 @@ makeDefaultPipeline(void) return pipe; } -// Skin plugin - -struct NativeSkin -{ - int32 table1[256]; // maps indices to bones - int32 table2[256]; // maps bones to indices - int32 numUsedBones; - void *vertexBuffer; - int32 stride; -}; - -Stream* -readNativeSkin(Stream *stream, int32, void *object, int32 offset) -{ - Geometry *geometry = (Geometry*)object; - uint32 vers, platform; - if(!findChunk(stream, ID_STRUCT, nil, &vers)){ - RWERROR((ERR_CHUNK, "STRUCT")) - return nil; - } - platform = stream->readU32(); - if(platform != PLATFORM_XBOX){ - RWERROR((ERR_PLATFORM, platform)); - return nil; - } - if(vers < 0x35000){ - RWERROR((ERR_VERSION, vers)); - return nil; - } - - Skin *skin = new Skin; - *PLUGINOFFSET(Skin*, geometry, offset) = skin; - - int32 numBones = stream->readI32(); - skin->init(numBones, 0, 0); - NativeSkin *natskin = new NativeSkin; - skin->platformData = natskin; - stream->read(natskin->table1, 256*sizeof(int32)); - stream->read(natskin->table2, 256*sizeof(int32)); - natskin->numUsedBones = stream->readI32(); - skin->numWeights = stream->readI32(); - stream->seek(4); // skip pointer to vertexBuffer - natskin->stride = stream->readI32(); - int32 size = geometry->numVertices*natskin->stride; - natskin->vertexBuffer = new uint8[size]; - stream->read(natskin->vertexBuffer, size); - stream->read(skin->inverseMatrices, skin->numBones*64); - - // no split skins in GTA - stream->seek(12); - return stream; -} - -Stream* -writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset) -{ - Geometry *geometry = (Geometry*)object; - Skin *skin = *PLUGINOFFSET(Skin*, object, offset); - assert(skin->platformData); - assert(rw::version >= 0x35000 && "can't handle native xbox skin < 0x35000"); - NativeSkin *natskin = (NativeSkin*)skin->platformData; - - writeChunkHeader(stream, ID_STRUCT, len-12); - stream->writeU32(PLATFORM_XBOX); - stream->writeI32(skin->numBones); - stream->write(natskin->table1, 256*sizeof(int32)); - stream->write(natskin->table2, 256*sizeof(int32)); - stream->writeI32(natskin->numUsedBones); - stream->writeI32(skin->numWeights); - stream->writeU32(0xBADEAFFE); // pointer to vertexBuffer - stream->writeI32(natskin->stride); - stream->write(natskin->vertexBuffer, - geometry->numVertices*natskin->stride); - stream->write(skin->inverseMatrices, skin->numBones*64); - int32 buffer[3] = { 0, 0, 0}; - stream->write(buffer, 12); - return stream; -} - -int32 -getSizeNativeSkin(void *object, int32 offset) -{ - Geometry *geometry = (Geometry*)object; - Skin *skin = *PLUGINOFFSET(Skin*, object, offset); - if(skin == nil) - return -1; - if(skin->platformData == nil) - return -1; - NativeSkin *natskin = (NativeSkin*)skin->platformData; - return 12 + 8 + 2*256*4 + 4*4 + - natskin->stride*geometry->numVertices + skin->numBones*64 + 12; -} - -void -skinInstanceCB(Geometry *geo, InstanceDataHeader *header) -{ - defaultInstanceCB(geo, header); - - Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); - if(skin == nil) - return; - NativeSkin *natskin = new NativeSkin; - skin->platformData = natskin; - - natskin->numUsedBones = skin->numUsedBones; - memset(natskin->table1, 0xFF, sizeof(natskin->table1)); - memset(natskin->table2, 0x00, sizeof(natskin->table2)); - for(int32 i = 0; i < skin->numUsedBones; i++){ - natskin->table1[i] = skin->usedBones[i]; - natskin->table2[skin->usedBones[i]] = i; - } - - natskin->stride = 3*skin->numWeights; - uint8 *vbuf = new uint8[header->numVertices*natskin->stride]; - natskin->vertexBuffer = vbuf; - - int32 w[4]; - int sum; - float *weights = skin->weights; - uint8 *p = vbuf; - int32 numVertices = header->numVertices; - while(numVertices--){ - sum = 0; - for(int i = 1; i < skin->numWeights; i++){ - w[i] = weights[i]*255.0f + 0.5f; - sum += w[i]; - } - w[0] = 255 - sum; - for(int i = 0; i < skin->numWeights; i++) - p[i] = w[i]; - p += natskin->stride; - weights += 4; - } - - numVertices = header->numVertices; - p = vbuf + skin->numWeights; - uint8 *indices = skin->indices; - uint16 *idx; - while(numVertices--){ - idx = (uint16*)p; - for(int i = 0; i < skin->numWeights; i++) - idx[i] = 3*natskin->table2[indices[i]]; - p += natskin->stride; - indices += 4; - } -} - -void -skinUninstanceCB(Geometry *geo, InstanceDataHeader *header) -{ - defaultUninstanceCB(geo, header); - - Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); - if(skin == nil) - return; - NativeSkin *natskin = (NativeSkin*)skin->platformData; - - uint8 *data = skin->data; - float *invMats = skin->inverseMatrices; - skin->init(skin->numBones, natskin->numUsedBones, geo->numVertices); - memcpy(skin->inverseMatrices, invMats, skin->numBones*64); - delete[] data; - - for(int32 j = 0; j < skin->numUsedBones; j++) - skin->usedBones[j] = natskin->table1[j]; - - float *weights = skin->weights; - uint8 *indices = skin->indices; - uint8 *p = (uint8*)natskin->vertexBuffer; - int32 numVertices = header->numVertices; - float w[4]; - uint8 i[4]; - uint16 *ip; - while(numVertices--){ - w[0] = w[1] = w[2] = w[3] = 0.0f; - i[0] = i[1] = i[2] = i[3] = 0; - - for(int32 j = 0; j < skin->numWeights; j++) - w[j] = *p++/255.0f; - - ip = (uint16*)p; - for(int32 j = 0; j < skin->numWeights; j++){ - i[j] = natskin->table1[*ip++/3]; - if(w[j] == 0.0f) i[j] = 0; // clean up a bit - } - p = (uint8*)ip; - - for(int32 j = 0; j < 4; j++){ - *weights++ = w[j]; - *indices++ = i[j]; - } - } - - delete[] (uint8*)natskin->vertexBuffer; - delete natskin; -} - -ObjPipeline* -makeSkinPipeline(void) -{ - ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX); - pipe->instanceCB = skinInstanceCB; - pipe->uninstanceCB = skinUninstanceCB; - pipe->pluginID = ID_SKIN; - pipe->pluginData = 1; - return pipe; -} - -ObjPipeline* -makeMatFXPipeline(void) -{ - ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX); - pipe->instanceCB = defaultInstanceCB; - pipe->uninstanceCB = defaultUninstanceCB; - pipe->pluginID = ID_MATFX; - pipe->pluginData = 0; - return pipe; -} - -// Vertex Format Plugin - -static int32 vertexFmtOffset; - -uint32 vertexFormatSizes[6] = { - 0, 1, 2, 2, 4, 4 -}; - -uint32* -getVertexFmt(Geometry *g) -{ - return PLUGINOFFSET(uint32, g, vertexFmtOffset); -} - -uint32 -makeVertexFmt(int32 flags, uint32 numTexSets) -{ - if(numTexSets > 4) - numTexSets = 4; - uint32 fmt = 0x5; // FLOAT3 - if(flags & Geometry::NORMALS) - fmt |= 0x40; // NORMPACKED3 - for(uint32 i = 0; i < numTexSets; i++) - fmt |= 0x500 << i*4; // FLOAT2 - if(flags & Geometry::PRELIT) - fmt |= 0x1000000; // D3DCOLOR - return fmt; -} - -uint32 -getVertexFmtStride(uint32 fmt) -{ - uint32 stride = 0; - uint32 v = fmt & 0xF; - uint32 n = (fmt >> 4) & 0xF; - stride += v == 4 ? 4 : 3*vertexFormatSizes[v]; - stride += n == 4 ? 4 : 3*vertexFormatSizes[n]; - if(fmt & 0x1000000) - stride += 4; - for(int i = 0; i < 4; i++){ - uint32 t = (fmt >> (i*4 + 8)) & 0xF; - stride += t == 4 ? 4 : 2*vertexFormatSizes[t]; - } - if(fmt & 0xE000000) - stride += 8; - return stride; -} - -static void* -createVertexFmt(void *object, int32 offset, int32) -{ - *PLUGINOFFSET(uint32, object, offset) = 0; - return object; -} - -static void* -copyVertexFmt(void *dst, void *src, int32 offset, int32) -{ - *PLUGINOFFSET(uint32, dst, offset) = *PLUGINOFFSET(uint32, src, offset); - return dst; -} - -static Stream* -readVertexFmt(Stream *stream, int32, void *object, int32 offset, int32) -{ - uint32 fmt = stream->readU32(); - *PLUGINOFFSET(uint32, object, offset) = fmt; - // TODO: ? create and attach "vertex shader" - return stream; -} - -static Stream* -writeVertexFmt(Stream *stream, int32, void *object, int32 offset, int32) -{ - stream->writeI32(*PLUGINOFFSET(uint32, object, offset)); - return stream; -} - -static int32 -getSizeVertexFmt(void*, int32, int32) -{ - if(rw::platform != PLATFORM_XBOX) - return -1; - return 4; -} - -void -registerVertexFormatPlugin(void) -{ - vertexFmtOffset = Geometry::registerPlugin(sizeof(uint32), ID_VERTEXFMT, - createVertexFmt, nil, copyVertexFmt); - Geometry::registerPluginStream(ID_VERTEXFMT, - readVertexFmt, - writeVertexFmt, - getSizeVertexFmt); -} - // Native Texture and Raster int32 nativeRasterOffset; @@ -790,7 +499,7 @@ createTexture(int32 width, int32 height, int32 numlevels, uint32 format) return levels; } -static void +void rasterCreate(Raster *raster) { XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset); @@ -840,7 +549,7 @@ rasterCreate(Raster *raster) format); } -static uint8* +uint8* rasterLock(Raster *raster, int32 level) { XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset); @@ -848,12 +557,12 @@ rasterLock(Raster *raster, int32 level) return levels->levels[level].data; } -static void +void rasterUnlock(Raster*, int32) { } -static int32 +int32 rasterNumLevels(Raster *raster) { XboxRaster *natras = PLUGINOFFSET(XboxRaster, raster, nativeRasterOffset); @@ -900,26 +609,9 @@ copyNativeRaster(void *dst, void *, int32 offset, int32) return dst; } -static void* -nativeOpen(void*, int32, int32) -{ - driver[PLATFORM_XBOX].rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_XBOX].rasterCreate = rasterCreate; - driver[PLATFORM_XBOX].rasterLock = rasterLock; - driver[PLATFORM_XBOX].rasterUnlock = rasterUnlock; - driver[PLATFORM_XBOX].rasterNumLevels = rasterNumLevels; -} - -static void* -nativeClose(void*, int32, int32) -{ - printf("xbox native close\n"); -} - void registerNativeRaster(void) { - Engine::registerPlugin(0, ID_RASTERXBOX, nativeOpen, nativeClose); nativeRasterOffset = Raster::registerPlugin(sizeof(XboxRaster), ID_RASTERXBOX, createNativeRaster, diff --git a/src/d3d/xboxplugins.cpp b/src/d3d/xboxplugins.cpp new file mode 100644 index 0000000..9ca6e36 --- /dev/null +++ b/src/d3d/xboxplugins.cpp @@ -0,0 +1,379 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwplugins.h" +#include "rwxbox.h" + +#define PLUGIN_ID ID_SKIN // yeah right.... + +namespace rw { +namespace xbox { + +// Skin + +struct NativeSkin +{ + int32 table1[256]; // maps indices to bones + int32 table2[256]; // maps bones to indices + int32 numUsedBones; + void *vertexBuffer; + int32 stride; +}; + +Stream* +readNativeSkin(Stream *stream, int32, void *object, int32 offset) +{ + Geometry *geometry = (Geometry*)object; + uint32 vers, platform; + if(!findChunk(stream, ID_STRUCT, nil, &vers)){ + RWERROR((ERR_CHUNK, "STRUCT")) + return nil; + } + platform = stream->readU32(); + if(platform != PLATFORM_XBOX){ + RWERROR((ERR_PLATFORM, platform)); + return nil; + } + if(vers < 0x35000){ + RWERROR((ERR_VERSION, vers)); + return nil; + } + + Skin *skin = new Skin; + *PLUGINOFFSET(Skin*, geometry, offset) = skin; + + int32 numBones = stream->readI32(); + skin->init(numBones, 0, 0); + NativeSkin *natskin = new NativeSkin; + skin->platformData = natskin; + stream->read(natskin->table1, 256*sizeof(int32)); + stream->read(natskin->table2, 256*sizeof(int32)); + natskin->numUsedBones = stream->readI32(); + skin->numWeights = stream->readI32(); + stream->seek(4); // skip pointer to vertexBuffer + natskin->stride = stream->readI32(); + int32 size = geometry->numVertices*natskin->stride; + natskin->vertexBuffer = new uint8[size]; + stream->read(natskin->vertexBuffer, size); + stream->read(skin->inverseMatrices, skin->numBones*64); + + // no split skins in GTA + stream->seek(12); + return stream; +} + +Stream* +writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset) +{ + Geometry *geometry = (Geometry*)object; + Skin *skin = *PLUGINOFFSET(Skin*, object, offset); + assert(skin->platformData); + assert(rw::version >= 0x35000 && "can't handle native xbox skin < 0x35000"); + NativeSkin *natskin = (NativeSkin*)skin->platformData; + + writeChunkHeader(stream, ID_STRUCT, len-12); + stream->writeU32(PLATFORM_XBOX); + stream->writeI32(skin->numBones); + stream->write(natskin->table1, 256*sizeof(int32)); + stream->write(natskin->table2, 256*sizeof(int32)); + stream->writeI32(natskin->numUsedBones); + stream->writeI32(skin->numWeights); + stream->writeU32(0xBADEAFFE); // pointer to vertexBuffer + stream->writeI32(natskin->stride); + stream->write(natskin->vertexBuffer, + geometry->numVertices*natskin->stride); + stream->write(skin->inverseMatrices, skin->numBones*64); + int32 buffer[3] = { 0, 0, 0}; + stream->write(buffer, 12); + return stream; +} + +int32 +getSizeNativeSkin(void *object, int32 offset) +{ + Geometry *geometry = (Geometry*)object; + Skin *skin = *PLUGINOFFSET(Skin*, object, offset); + if(skin == nil) + return -1; + if(skin->platformData == nil) + return -1; + NativeSkin *natskin = (NativeSkin*)skin->platformData; + return 12 + 8 + 2*256*4 + 4*4 + + natskin->stride*geometry->numVertices + skin->numBones*64 + 12; +} + +void +skinInstanceCB(Geometry *geo, InstanceDataHeader *header) +{ + defaultInstanceCB(geo, header); + + Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); + if(skin == nil) + return; + NativeSkin *natskin = new NativeSkin; + skin->platformData = natskin; + + natskin->numUsedBones = skin->numUsedBones; + memset(natskin->table1, 0xFF, sizeof(natskin->table1)); + memset(natskin->table2, 0x00, sizeof(natskin->table2)); + for(int32 i = 0; i < skin->numUsedBones; i++){ + natskin->table1[i] = skin->usedBones[i]; + natskin->table2[skin->usedBones[i]] = i; + } + + natskin->stride = 3*skin->numWeights; + uint8 *vbuf = new uint8[header->numVertices*natskin->stride]; + natskin->vertexBuffer = vbuf; + + int32 w[4]; + int sum; + float *weights = skin->weights; + uint8 *p = vbuf; + int32 numVertices = header->numVertices; + while(numVertices--){ + sum = 0; + for(int i = 1; i < skin->numWeights; i++){ + w[i] = weights[i]*255.0f + 0.5f; + sum += w[i]; + } + w[0] = 255 - sum; + for(int i = 0; i < skin->numWeights; i++) + p[i] = w[i]; + p += natskin->stride; + weights += 4; + } + + numVertices = header->numVertices; + p = vbuf + skin->numWeights; + uint8 *indices = skin->indices; + uint16 *idx; + while(numVertices--){ + idx = (uint16*)p; + for(int i = 0; i < skin->numWeights; i++) + idx[i] = 3*natskin->table2[indices[i]]; + p += natskin->stride; + indices += 4; + } +} + +void +skinUninstanceCB(Geometry *geo, InstanceDataHeader *header) +{ + defaultUninstanceCB(geo, header); + + Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); + if(skin == nil) + return; + NativeSkin *natskin = (NativeSkin*)skin->platformData; + + uint8 *data = skin->data; + float *invMats = skin->inverseMatrices; + skin->init(skin->numBones, natskin->numUsedBones, geo->numVertices); + memcpy(skin->inverseMatrices, invMats, skin->numBones*64); + delete[] data; + + for(int32 j = 0; j < skin->numUsedBones; j++) + skin->usedBones[j] = natskin->table1[j]; + + float *weights = skin->weights; + uint8 *indices = skin->indices; + uint8 *p = (uint8*)natskin->vertexBuffer; + int32 numVertices = header->numVertices; + float w[4]; + uint8 i[4]; + uint16 *ip; + while(numVertices--){ + w[0] = w[1] = w[2] = w[3] = 0.0f; + i[0] = i[1] = i[2] = i[3] = 0; + + for(int32 j = 0; j < skin->numWeights; j++) + w[j] = *p++/255.0f; + + ip = (uint16*)p; + for(int32 j = 0; j < skin->numWeights; j++){ + i[j] = natskin->table1[*ip++/3]; + if(w[j] == 0.0f) i[j] = 0; // clean up a bit + } + p = (uint8*)ip; + + for(int32 j = 0; j < 4; j++){ + *weights++ = w[j]; + *indices++ = i[j]; + } + } + + delete[] (uint8*)natskin->vertexBuffer; + delete natskin; +} + +static void* +skinOpen(void *o, int32, int32) +{ + skinGlobals.pipelines[PLATFORM_XBOX] = makeSkinPipeline(); + return o; +} + +static void* +skinClose(void *o, int32, int32) +{ + return o; +} + +void +initSkin(void) +{ + Driver::registerPlugin(PLATFORM_XBOX, 0, ID_SKIN, + skinOpen, skinClose); +} + +ObjPipeline* +makeSkinPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX); + pipe->instanceCB = skinInstanceCB; + pipe->uninstanceCB = skinUninstanceCB; + pipe->pluginID = ID_SKIN; + pipe->pluginData = 1; + return pipe; +} + +// MatFX + +static void* +matfxOpen(void *o, int32, int32) +{ + matFXGlobals.pipelines[PLATFORM_XBOX] = makeMatFXPipeline(); + return o; +} + +static void* +matfxClose(void *o, int32, int32) +{ + return o; +} + +void +initMatFX(void) +{ + Driver::registerPlugin(PLATFORM_XBOX, 0, ID_MATFX, + matfxOpen, matfxClose); +} + +ObjPipeline* +makeMatFXPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->pluginID = ID_MATFX; + pipe->pluginData = 0; + return pipe; +} + +// Vertex Format + +static int32 vertexFmtOffset; + +uint32 vertexFormatSizes[6] = { + 0, 1, 2, 2, 4, 4 +}; + +uint32* +getVertexFmt(Geometry *g) +{ + return PLUGINOFFSET(uint32, g, vertexFmtOffset); +} + +uint32 +makeVertexFmt(int32 flags, uint32 numTexSets) +{ + if(numTexSets > 4) + numTexSets = 4; + uint32 fmt = 0x5; // FLOAT3 + if(flags & Geometry::NORMALS) + fmt |= 0x40; // NORMPACKED3 + for(uint32 i = 0; i < numTexSets; i++) + fmt |= 0x500 << i*4; // FLOAT2 + if(flags & Geometry::PRELIT) + fmt |= 0x1000000; // D3DCOLOR + return fmt; +} + +uint32 +getVertexFmtStride(uint32 fmt) +{ + uint32 stride = 0; + uint32 v = fmt & 0xF; + uint32 n = (fmt >> 4) & 0xF; + stride += v == 4 ? 4 : 3*vertexFormatSizes[v]; + stride += n == 4 ? 4 : 3*vertexFormatSizes[n]; + if(fmt & 0x1000000) + stride += 4; + for(int i = 0; i < 4; i++){ + uint32 t = (fmt >> (i*4 + 8)) & 0xF; + stride += t == 4 ? 4 : 2*vertexFormatSizes[t]; + } + if(fmt & 0xE000000) + stride += 8; + return stride; +} + +static void* +createVertexFmt(void *object, int32 offset, int32) +{ + *PLUGINOFFSET(uint32, object, offset) = 0; + return object; +} + +static void* +copyVertexFmt(void *dst, void *src, int32 offset, int32) +{ + *PLUGINOFFSET(uint32, dst, offset) = *PLUGINOFFSET(uint32, src, offset); + return dst; +} + +static Stream* +readVertexFmt(Stream *stream, int32, void *object, int32 offset, int32) +{ + uint32 fmt = stream->readU32(); + *PLUGINOFFSET(uint32, object, offset) = fmt; + // TODO: ? create and attach "vertex shader" + return stream; +} + +static Stream* +writeVertexFmt(Stream *stream, int32, void *object, int32 offset, int32) +{ + stream->writeI32(*PLUGINOFFSET(uint32, object, offset)); + return stream; +} + +static int32 +getSizeVertexFmt(void*, int32, int32) +{ + if(rw::platform != PLATFORM_XBOX) + return -1; + return 4; +} + +void +registerVertexFormatPlugin(void) +{ + vertexFmtOffset = Geometry::registerPlugin(sizeof(uint32), ID_VERTEXFMT, + createVertexFmt, nil, copyVertexFmt); + Geometry::registerPluginStream(ID_VERTEXFMT, + readVertexFmt, + writeVertexFmt, + getSizeVertexFmt); +} + +} +} diff --git a/src/engine.cpp b/src/engine.cpp index bccff03..a2a6f9b 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -18,26 +18,16 @@ namespace rw { Engine *engine; -Driver driver[NUM_PLATFORMS]; - -PluginList Engine::s_plglist = {sizeof(Engine), sizeof(Engine), nil, nil}; +Driver *driver[NUM_PLATFORMS]; void Engine::init(void) { - ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); - for(uint i = 0; i < NUM_PLATFORMS; i++){ - driver[i].defaultPipeline = defpipe; + engine = new Engine; - driver[i].beginUpdate = null::beginUpdate; - driver[i].endUpdate = null::endUpdate; + for(uint i = 0; i < NUM_PLATFORMS; i++) + Driver::s_plglist[i] = { sizeof(Driver), sizeof(Driver), nil, nil }; - driver[i].rasterCreate = null::rasterCreate; - driver[i].rasterLock = null::rasterLock; - driver[i].rasterUnlock = null::rasterUnlock; - driver[i].rasterNumLevels = null::rasterNumLevels; - driver[i].rasterFromImage = null::rasterFromImage; - } Frame::dirtyList.init(); ps2::initializePlatform(); @@ -48,11 +38,29 @@ Engine::init(void) gl3::initializePlatform(); } +PluginList Driver::s_plglist[NUM_PLATFORMS]; + void -Engine::open(void) +Driver::open(void) { - rw::engine = (Engine*)malloc(s_plglist.size); - s_plglist.construct(rw::engine); + ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); + + for(uint i = 0; i < NUM_PLATFORMS; i++){ + rw::driver[i] = (Driver*)malloc(s_plglist[i].size); + + driver[i]->defaultPipeline = defpipe; + + driver[i]->beginUpdate = null::beginUpdate; + driver[i]->endUpdate = null::endUpdate; + + driver[i]->rasterCreate = null::rasterCreate; + driver[i]->rasterLock = null::rasterLock; + driver[i]->rasterUnlock = null::rasterUnlock; + driver[i]->rasterNumLevels = null::rasterNumLevels; + driver[i]->rasterFromImage = null::rasterFromImage; + + s_plglist[i].construct(rw::driver[i]); + } } namespace null { diff --git a/src/gl/gl3.cpp b/src/gl/gl3.cpp new file mode 100644 index 0000000..83baa17 --- /dev/null +++ b/src/gl/gl3.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwplugins.h" +#ifdef RW_OPENGL +#include +#endif +#include "rwgl3.h" +#include "rwgl3shader.h" + +#include "rwgl3impl.h" + +namespace rw { +namespace gl3 { + +// TODO: make some of these things platform-independent + +void* +driverOpen(void *o, int32, int32) +{ + printf("gl3 open\n"); +#ifdef RW_OPENGL + driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline(); +#endif + driver[PLATFORM_GL3]->rasterNativeOffset = nativeRasterOffset; + driver[PLATFORM_GL3]->rasterCreate = rasterCreate; + driver[PLATFORM_GL3]->rasterLock = rasterLock; + driver[PLATFORM_GL3]->rasterUnlock = rasterUnlock; + driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; + driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; + + initializeRender(); + + return o; +} + +void* +driverClose(void *o, int32, int32) +{ + return o; +} + +void +initializePlatform(void) +{ + Driver::registerPlugin(PLATFORM_GL3, 0, PLATFORM_GL3, + driverOpen, driverClose); + + registerNativeRaster(); + +#ifdef RW_OPENGL + // uniforms need to be registered before any shaders are created + registerBlock("Scene"); + registerBlock("Object"); + registerBlock("State"); + registerUniform("u_matColor"); + registerUniform("u_surfaceProps"); +#endif +} + +} +} diff --git a/src/gl/gl3pipe.cpp b/src/gl/gl3pipe.cpp index dce41e0..542150e 100644 --- a/src/gl/gl3pipe.cpp +++ b/src/gl/gl3pipe.cpp @@ -21,23 +21,6 @@ namespace gl3 { // TODO: make some of these things platform-independent -void -initializePlatform(void) -{ - registerNativeRaster(); -#ifdef RW_OPENGL - driver[PLATFORM_GL3].defaultPipeline = makeDefaultPipeline(); - - // uniforms need to be registered before any shaders are created - registerBlock("Scene"); - registerBlock("Object"); - registerUniform("u_matColor"); - registerUniform("u_surfaceProps"); -#endif - - initializeRender(); -} - #ifdef RW_OPENGL static void @@ -251,30 +234,6 @@ makeDefaultPipeline(void) return pipe; } -ObjPipeline* -makeSkinPipeline(void) -{ - ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3); - pipe->instanceCB = defaultInstanceCB; - pipe->uninstanceCB = defaultUninstanceCB; - pipe->renderCB = defaultRenderCB; - pipe->pluginID = ID_SKIN; - pipe->pluginData = 1; - return pipe; -} - -ObjPipeline* -makeMatFXPipeline(void) -{ - ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3); - pipe->instanceCB = defaultInstanceCB; - pipe->uninstanceCB = defaultUninstanceCB; - pipe->renderCB = defaultRenderCB; - pipe->pluginID = ID_MATFX; - pipe->pluginData = 0; - return pipe; -} - #endif } diff --git a/src/gl/gl3plugins.cpp b/src/gl/gl3plugins.cpp new file mode 100644 index 0000000..a8dff53 --- /dev/null +++ b/src/gl/gl3plugins.cpp @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwplugins.h" +#ifdef RW_OPENGL +#include +#endif +#include "rwgl3.h" +#include "rwgl3shader.h" + +namespace rw { +namespace gl3 { + +#ifdef RW_OPENGL + +// MatFX + +static void* +matfxOpen(void *o, int32, int32) +{ + matFXGlobals.pipelines[PLATFORM_GL3] = makeMatFXPipeline(); + return o; +} + +static void* +matfxClose(void *o, int32, int32) +{ + return o; +} + +void +initMatFX(void) +{ + Driver::registerPlugin(PLATFORM_GL3, 0, ID_MATFX, + matfxOpen, matfxClose); +} + +ObjPipeline* +makeMatFXPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = matfxRenderCB; + pipe->pluginID = ID_MATFX; + pipe->pluginData = 0; + return pipe; +} + +// Skin + +static void* +skinOpen(void *o, int32, int32) +{ + skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline(); + return o; +} + +static void* +skinClose(void *o, int32, int32) +{ + return o; +} + +void +initSkin(void) +{ + Driver::registerPlugin(PLATFORM_GL3, 0, ID_SKIN, + skinOpen, skinClose); +} + +ObjPipeline* +makeSkinPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_GL3); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; + pipe->pluginID = ID_SKIN; + pipe->pluginData = 1; + return pipe; +} + +#endif + +} +} diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index 2b2113f..205f9a6 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -21,7 +21,7 @@ namespace gl3 { int32 nativeRasterOffset; -static void +void rasterCreate(Raster *raster) { Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); @@ -42,27 +42,27 @@ rasterCreate(Raster *raster) #endif } -static uint8* +uint8* rasterLock(Raster*, int32 level) { printf("locking\n"); return nil; } -static void +void rasterUnlock(Raster*, int32) { printf("unlocking\n"); } -static int32 +int32 rasterNumLevels(Raster*) { printf("numlevels\n"); return 0; } -static void +void rasterFromImage(Raster *raster, Image *image) { int32 format; @@ -112,26 +112,8 @@ copyNativeRaster(void *dst, void *, int32 offset, int32) return dst; } -static void* -nativeOpen(void*, int32, int32) -{ - driver[PLATFORM_GL3].rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_GL3].rasterCreate = rasterCreate; - driver[PLATFORM_GL3].rasterLock = rasterLock; - driver[PLATFORM_GL3].rasterUnlock = rasterUnlock; - driver[PLATFORM_GL3].rasterNumLevels = rasterNumLevels; - driver[PLATFORM_GL3].rasterFromImage = rasterFromImage; -} - -static void* -nativeClose(void*, int32, int32) -{ - printf("gl3 native close\n"); -} - void registerNativeRaster(void) { - Engine::registerPlugin(0, ID_RASTERGL3, nativeOpen, nativeClose); nativeRasterOffset = Raster::registerPlugin(sizeof(Gl3Raster), ID_RASTERGL3, createNativeRaster, diff --git a/src/gl/gl3render.cpp b/src/gl/gl3render.cpp index 91feb20..1fb3878 100644 --- a/src/gl/gl3render.cpp +++ b/src/gl/gl3render.cpp @@ -17,6 +17,12 @@ namespace rw { namespace gl3 { +struct UniformState +{ + int alphaFunc; + float32 alphaRef; +}; + struct UniformScene { float32 proj[16]; @@ -47,8 +53,9 @@ struct UniformObject }; GLuint vao; -GLuint ubo_scene, ubo_object; +GLuint ubo_state, ubo_scene, ubo_object; GLuint whitetex; +UniformState uniformState; UniformScene uniformScene; UniformObject uniformObject; @@ -113,7 +120,7 @@ beginUpdate(Camera *cam) void initializeRender(void) { - driver[PLATFORM_GL3].beginUpdate = beginUpdate; + driver[PLATFORM_GL3]->beginUpdate = beginUpdate; glClearColor(0.25, 0.25, 0.25, 1.0); @@ -125,6 +132,14 @@ initializeRender(void) glGenVertexArrays(1, &vao); glBindVertexArray(vao); + glGenBuffers(1, &ubo_state); + glBindBuffer(GL_UNIFORM_BUFFER, ubo_state); + glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("State"), ubo_state); + glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformState), &uniformState, + GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glGenBuffers(1, &ubo_scene); glBindBuffer(GL_UNIFORM_BUFFER, ubo_scene); glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("Scene"), ubo_scene); @@ -163,6 +178,7 @@ setAttribPointers(InstanceDataHeader *header) } } +static bool32 stateDirty = 1; static bool32 sceneDirty = 1; static bool32 objectDirty = 1; @@ -262,6 +278,21 @@ setVertexAlpha(bool32 alpha) vertexAlpha = alpha; } +void +setAlphaTestFunc(int32 f) +{ + uniformState.alphaFunc = f; + stateDirty = 1; +} + +void +setAlphaRef(float32 f) +{ + uniformState.alphaRef = f; + stateDirty = 1; +} + +#define U(s) currentShader->uniformLocations[findUniform(s)] void flushCache(void) @@ -278,6 +309,12 @@ flushCache(void) &uniformScene); sceneDirty = 0; } + if(stateDirty){ + glBindBuffer(GL_UNIFORM_BUFFER, ubo_state); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformState), + &uniformState); + stateDirty = 0; + } } void @@ -305,6 +342,56 @@ lightingCB(void) setAmbientLight(&ambLight); } +void +matfxRenderCB(Atomic *atomic, InstanceDataHeader *header) +{ + setWorldMatrix(atomic->getFrame()->getLTM()); + lightingCB(); + + glBindBuffer(GL_ARRAY_BUFFER, header->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); + setAttribPointers(header); + + Material *m; + RGBAf col; + GLfloat surfProps[4]; + int id; + InstanceData *inst = header->inst; + int32 n = header->numMeshes; + + setAlphaTestFunc(1); + setAlphaRef(0.2); + + while(n--){ + m = inst->material; + + convColor(&col, &m->color); + glUniform4fv(U("u_matColor"), 1, (GLfloat*)&col); + + surfProps[0] = m->surfaceProps.ambient; + surfProps[1] = m->surfaceProps.specular; + surfProps[2] = m->surfaceProps.diffuse; + surfProps[3] = 0.0f; + glUniform4fv(U("u_surfaceProps"), 1, surfProps); + + setTexture(0, m->texture); +/* + if(MatFX::getEffects(m) == MatFX::ENVMAP){ + MatFX *fx = MatFX::get(m); + int32 idx = fx->getEffectIndex(MatFX::ENVMAP); + setTexture(0, fx->fx[idx].env.tex); + } +*/ + + setVertexAlpha(inst->vertexAlpha || m->color.alpha != 0xFF); + + flushCache(); + glDrawElements(header->primType, inst->numIndex, + GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset); + inst++; + } +} + void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) { @@ -322,11 +409,12 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) InstanceData *inst = header->inst; int32 n = header->numMeshes; + setAlphaTestFunc(1); + setAlphaRef(0.2); + while(n--){ m = inst->material; -#define U(s) currentShader->uniformLocations[findUniform(s)] - convColor(&col, &m->color); glUniform4fv(U("u_matColor"), 1, (GLfloat*)&col); diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 27236da..3419dbb 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -60,6 +60,10 @@ struct InstanceDataHeader : rw::InstanceDataHeader void setAttribPointers(InstanceDataHeader *header); +// Render state +void setAlphaTestFunc(int32 f); +void setAlphaRef(float32 f); + // per Scene void setProjectionMatrix(float32*); void setViewMatrix(float32*); @@ -88,6 +92,8 @@ void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header); void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header); void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header); +void matfxRenderCB(Atomic *atomic, InstanceDataHeader *header); + ObjPipeline *makeDefaultPipeline(void); ObjPipeline *makeSkinPipeline(void); ObjPipeline *makeMatFXPipeline(void); diff --git a/src/gl/rwgl3impl.h b/src/gl/rwgl3impl.h new file mode 100644 index 0000000..d2a6821 --- /dev/null +++ b/src/gl/rwgl3impl.h @@ -0,0 +1,11 @@ +namespace rw { +namespace gl3 { + +void rasterCreate(Raster *raster); +uint8 *rasterLock(Raster*, int32 level); +void rasterUnlock(Raster*, int32); +int32 rasterNumLevels(Raster*); +void rasterFromImage(Raster *raster, Image *image); + +} +} diff --git a/src/gl/rwgl3plg.h b/src/gl/rwgl3plg.h new file mode 100644 index 0000000..75ace8e --- /dev/null +++ b/src/gl/rwgl3plg.h @@ -0,0 +1,13 @@ +namespace rw { +namespace gl3 { + +void matfxRenderCB(Atomic *atomic, InstanceDataHeader *header); + +ObjPipeline *makeSkinPipeline(void); +ObjPipeline *makeMatFXPipeline(void); + +void initMatFX(void); +void initSkin(void); + +} +} diff --git a/src/gl/rwwdgl.h b/src/gl/rwwdgl.h index badf959..b9cf02d 100644 --- a/src/gl/rwwdgl.h +++ b/src/gl/rwwdgl.h @@ -60,12 +60,16 @@ ObjPipeline *makeDefaultPipeline(void); // Skin plugin +void initSkin(void); Stream *readNativeSkin(Stream *stream, int32, void *object, int32 offset); Stream *writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset); int32 getSizeNativeSkin(void *object, int32 offset); ObjPipeline *makeSkinPipeline(void); +// MatFX plugin + +void initMatFX(void); ObjPipeline *makeMatFXPipeline(void); // Raster diff --git a/src/gl/wdgl.cpp b/src/gl/wdgl.cpp index ba669f9..826e9b0 100644 --- a/src/gl/wdgl.cpp +++ b/src/gl/wdgl.cpp @@ -21,10 +21,25 @@ namespace rw { namespace wdgl { +void* +driverOpen(void *o, int32, int32) +{ + printf("wdgl open\n"); + driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline(); + return o; +} + +void* +driverClose(void *o, int32, int32) +{ + return o; +} + void initializePlatform(void) { - driver[PLATFORM_WDGL].defaultPipeline = makeDefaultPipeline(); + Driver::registerPlugin(PLATFORM_WDGL, 0, PLATFORM_WDGL, + driverOpen, driverClose); } @@ -659,6 +674,28 @@ skinUninstanceCB(Geometry *geo) skin->findUsedBones(geo->numVertices); } +// Skin + +static void* +skinOpen(void *o, int32, int32) +{ + skinGlobals.pipelines[PLATFORM_WDGL] = makeSkinPipeline(); + return o; +} + +static void* +skinClose(void *o, int32, int32) +{ + return o; +} + +void +initSkin(void) +{ + Driver::registerPlugin(PLATFORM_WDGL, 0, ID_SKIN, + skinOpen, skinClose); +} + ObjPipeline* makeSkinPipeline(void) { @@ -671,6 +708,28 @@ makeSkinPipeline(void) return pipe; } +// MatFX + +static void* +matfxOpen(void *o, int32, int32) +{ + matFXGlobals.pipelines[PLATFORM_WDGL] = makeMatFXPipeline(); + return o; +} + +static void* +matfxClose(void *o, int32, int32) +{ + return o; +} + +void +initMatFX(void) +{ + Driver::registerPlugin(PLATFORM_WDGL, 0, ID_MATFX, + matfxOpen, matfxClose); +} + ObjPipeline* makeMatFXPipeline(void) { diff --git a/src/image.cpp b/src/image.cpp index 7a37db4..9548845 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -691,7 +691,7 @@ Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platf raster->texels = raster->palette = nil; s_plglist.construct(raster); - driver[raster->platform].rasterCreate(raster); + driver[raster->platform]->rasterCreate(raster); return raster; } @@ -707,19 +707,19 @@ Raster::destroy(void) uint8* Raster::lock(int32 level) { - return driver[this->platform].rasterLock(this, level); + return driver[this->platform]->rasterLock(this, level); } void Raster::unlock(int32 level) { - driver[this->platform].rasterUnlock(this, level); + driver[this->platform]->rasterUnlock(this, level); } int32 Raster::getNumLevels(void) { - return driver[this->platform].rasterNumLevels(this); + return driver[this->platform]->rasterNumLevels(this); } int32 @@ -737,7 +737,7 @@ Raster::createFromImage(Image *image) { Raster *raster = Raster::create(image->width, image->height, image->depth, 4 | 0x80); - driver[raster->platform].rasterFromImage(raster, image); + driver[raster->platform]->rasterFromImage(raster, image); return raster; } diff --git a/src/matfx.cpp b/src/matfx.cpp index 90cd454..7381321 100644 --- a/src/matfx.cpp +++ b/src/matfx.cpp @@ -17,6 +17,7 @@ #include "d3d/rwd3d9.h" #include "gl/rwwdgl.h" #include "gl/rwgl3.h" +#include "gl/rwgl3plg.h" #define PLUGIN_ID ID_MATFX @@ -128,6 +129,12 @@ MatFX::getEffects(Material *m) return 0; } +MatFX* +MatFX::get(Material *m) +{ + return *PLUGINOFFSET(MatFX*, m, matFXGlobals.materialOffset); +} + uint32 MatFX::getEffectIndex(uint32 type) { @@ -410,28 +417,6 @@ MatFX::enableEffects(Atomic *atomic) atomic->pipeline = matFXGlobals.pipelines[rw::platform]; } -static void* -matfxOpen(void*, int32, int32) -{ - matFXGlobals.pipelines[PLATFORM_PS2] = - ps2::makeMatFXPipeline(); - matFXGlobals.pipelines[PLATFORM_XBOX] = - xbox::makeMatFXPipeline(); - matFXGlobals.pipelines[PLATFORM_D3D8] = - d3d8::makeMatFXPipeline(); - matFXGlobals.pipelines[PLATFORM_D3D9] = - d3d9::makeMatFXPipeline(); - matFXGlobals.pipelines[PLATFORM_WDGL] = - wdgl::makeMatFXPipeline(); - matFXGlobals.pipelines[PLATFORM_GL3] = - gl3::makeMatFXPipeline(); -} - -static void* -matfxClose(void*, int32, int32) -{ -} - void registerMatFXPlugin(void) { @@ -442,10 +427,12 @@ registerMatFXPlugin(void) for(uint i = 0; i < nelem(matFXGlobals.pipelines); i++) matFXGlobals.pipelines[i] = defpipe; - // TODO: call platform specific init functions? - // have platform specific open functions? - - Engine::registerPlugin(0, ID_MATFX, matfxOpen, matfxClose); + ps2::initMatFX(); + xbox::initMatFX(); + d3d8::initMatFX(); + d3d9::initMatFX(); + wdgl::initMatFX(); + gl3::initMatFX(); matFXGlobals.atomicOffset = Atomic::registerPlugin(sizeof(int32), ID_MATFX, diff --git a/src/ps2/ps2.cpp b/src/ps2/ps2.cpp index 8468bec..6bba416 100644 --- a/src/ps2/ps2.cpp +++ b/src/ps2/ps2.cpp @@ -13,16 +13,40 @@ #include "rwps2.h" #include "rwps2plg.h" +#include "rwps2impl.h" + #define PLUGIN_ID 2 namespace rw { namespace ps2 { +void* +driverOpen(void *o, int32, int32) +{ + printf("ps2 open\n"); + driver[PLATFORM_PS2]->defaultPipeline = makeDefaultPipeline(); + + driver[PLATFORM_PS2]->rasterNativeOffset = nativeRasterOffset; + driver[PLATFORM_PS2]->rasterCreate = rasterCreate; + driver[PLATFORM_PS2]->rasterLock = rasterLock; + driver[PLATFORM_PS2]->rasterUnlock = rasterUnlock; + driver[PLATFORM_PS2]->rasterNumLevels = rasterNumLevels; + return o; +} + +void* +driverClose(void *o, int32, int32) +{ + return o; +} + void initializePlatform(void) { + Driver::registerPlugin(PLATFORM_PS2, 0, PLATFORM_PS2, + driverOpen, driverClose); + registerNativeRaster(); - driver[PLATFORM_PS2].defaultPipeline = makeDefaultPipeline(); } ObjPipeline *defaultObjPipe; @@ -1068,315 +1092,6 @@ makeDefaultPipeline(void) return defaultObjPipe; } -ObjPipeline* -makeSkinPipeline(void) -{ - MatPipeline *pipe = new MatPipeline(PLATFORM_PS2); - pipe->pluginID = ID_SKIN; - pipe->pluginData = 1; - pipe->attribs[AT_XYZ] = &attribXYZ; - pipe->attribs[AT_UV] = &attribUV; - pipe->attribs[AT_RGBA] = &attribRGBA; - pipe->attribs[AT_NORMAL] = &attribNormal; - pipe->attribs[AT_NORMAL+1] = &attribWeights; - uint32 vertCount = MatPipeline::getVertCount(VU_Lights-0x100, 5, 3, 2); - pipe->setTriBufferSizes(5, vertCount); - pipe->vifOffset = pipe->inputStride*vertCount; - pipe->instanceCB = skinInstanceCB; - pipe->uninstanceCB = genericUninstanceCB; - pipe->preUninstCB = skinPreCB; - pipe->postUninstCB = skinPostCB; - - ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2); - opipe->pluginID = ID_SKIN; - opipe->pluginData = 1; - opipe->groupPipeline = pipe; - return opipe; -} - -ObjPipeline* -makeMatFXPipeline(void) -{ - MatPipeline *pipe = new MatPipeline(PLATFORM_PS2); - pipe->pluginID = ID_MATFX; - pipe->pluginData = 0; - pipe->attribs[AT_XYZ] = &attribXYZ; - pipe->attribs[AT_UV] = &attribUV; - pipe->attribs[AT_RGBA] = &attribRGBA; - pipe->attribs[AT_NORMAL] = &attribNormal; - uint32 vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3); - pipe->setTriBufferSizes(4, vertCount); - pipe->vifOffset = pipe->inputStride*vertCount; - pipe->uninstanceCB = genericUninstanceCB; - - ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2); - opipe->pluginID = ID_MATFX; - opipe->pluginData = 0; - opipe->groupPipeline = pipe; - return opipe; -} - -// Skin - -Stream* -readNativeSkin(Stream *stream, int32, void *object, int32 offset) -{ - uint8 header[4]; - Geometry *geometry = (Geometry*)object; - uint32 platform; - if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) - return nil; - } - platform = stream->readU32(); - if(platform != PLATFORM_PS2){ - RWERROR((ERR_PLATFORM, platform)); - return nil; - } - stream->read(header, 4); - Skin *skin = new Skin; - *PLUGINOFFSET(Skin*, geometry, offset) = skin; - - // numUsedBones and numWeights appear in/after 34003 but not in/before 33002 - // (probably rw::version >= 0x34000) - bool oldFormat = header[1] == 0; - - // Use numBones for numUsedBones to allocate data - if(oldFormat) - skin->init(header[0], header[0], 0); - else - skin->init(header[0], header[1], 0); - skin->numWeights = header[2]; - - if(!oldFormat) - stream->read(skin->usedBones, skin->numUsedBones); - if(skin->numBones) - stream->read(skin->inverseMatrices, skin->numBones*64); - - // dummy data in case we need to write data in the new format - if(oldFormat){ - skin->numWeights = 4; - for(int32 i = 0; i < skin->numUsedBones; i++) - skin->usedBones[i] = i; - } - - if(!oldFormat) - // last 3 ints are split data as in the other formats - // TODO: what are the other 4? - stream->seek(7*4); - return stream; -} - -Stream* -writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset) -{ - uint8 header[4]; - - writeChunkHeader(stream, ID_STRUCT, len-12); - stream->writeU32(PLATFORM_PS2); - Skin *skin = *PLUGINOFFSET(Skin*, object, offset); - // not sure which version introduced the new format - bool oldFormat = version < 0x34000; - header[0] = skin->numBones; - if(oldFormat){ - header[1] = 0; - header[2] = 0; - }else{ - header[1] = skin->numUsedBones; - header[2] = skin->numWeights; - } - header[3] = 0; - stream->write(header, 4); - - if(!oldFormat) - stream->write(skin->usedBones, skin->numUsedBones); - stream->write(skin->inverseMatrices, skin->numBones*64); - if(!oldFormat){ - uint32 buffer[7] = { 0, 0, 0, 0, 0, 0, 0 }; - stream->write(buffer, 7*4); - } - return stream; -} - -int32 -getSizeNativeSkin(void *object, int32 offset) -{ - Skin *skin = *PLUGINOFFSET(Skin*, object, offset); - if(skin == nil) - return -1; - int32 size = 12 + 4 + 4 + skin->numBones*64; - // not sure which version introduced the new format - if(version >= 0x34000) - size += skin->numUsedBones + 16 + 12; - return size; -} - -void -instanceSkinData(Geometry*, Mesh *m, Skin *skin, uint32 *data) -{ - uint16 j; - float32 *weights = (float32*)data; - uint32 *indices = data; - for(uint32 i = 0; i < m->numIndices; i++){ - j = m->indices[i]; - for(int32 k = 0; k < 4; k++){ - *weights++ = skin->weights[j*4+k]; - *indices &= ~0x3FF; - *indices++ |= skin->indices[j*4+k] && skin->weights[j*4+k] ? - (skin->indices[j*4+k]+1) << 2 : 0; - } - } -} - -void -skinInstanceCB(MatPipeline *, Geometry *g, Mesh *m, uint8 **data) -{ - Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset); - if(skin == nil) - return; - instanceSkinData(g, m, skin, (uint32*)data[4]); -} - -// TODO: call base function perhaps? -int32 -findVertexSkin(Geometry *g, uint32 flags[], uint32 mask, Vertex *v) -{ - Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset); - float32 *wghts = nil; - uint8 *inds = nil; - if(skin){ - wghts = skin->weights; - inds = skin->indices; - } - - float32 *verts = g->morphTargets[0].vertices; - float32 *tex = g->texCoords[0]; - float32 *tex1 = g->texCoords[1]; - float32 *norms = g->morphTargets[0].normals; - uint8 *cols = g->colors; - - for(int32 i = 0; i < g->numVertices; i++){ - 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 & flag & 0x10 && - !(norms[0] == v->n[0] && norms[1] == v->n[1] && norms[2] == v->n[2])) - goto cont; - if(mask & flag & 0x100 && - !(cols[0] == v->c[0] && cols[1] == v->c[1] && cols[2] == v->c[2] && cols[3] == v->c[3])) - goto cont; - if(mask & flag & 0x1000 && - !(tex[0] == v->t[0] && tex[1] == v->t[1])) - goto cont; - if(mask & flag & 0x2000 && - !(tex1[0] == v->t1[0] && tex1[1] == v->t1[1])) - goto cont; - 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] && - inds[2] == v->i[2] && inds[3] == v->i[3])) - goto cont; - return i; - cont: - verts += 3; - tex += 2; - norms += 3; - cols += 4; - wghts += 4; - inds += 4; - } - return -1; -} - -void -insertVertexSkin(Geometry *geo, int32 i, uint32 mask, Vertex *v) -{ - Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); - insertVertex(geo, i, mask, v); - if(mask & 0x10000){ - memcpy(&skin->weights[i*4], v->w, 16); - memcpy(&skin->indices[i*4], v->i, 4); - } -} - -/* -void -skinUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[]) -{ - float32 *verts = (float32*)data[AT_XYZ]; - float32 *texcoords = (float32*)data[AT_UV]; - uint8 *colors = (uint8*)data[AT_RGBA]; - int8 *norms = (int8*)data[AT_NORMAL]; - uint32 *wghts = (uint32*)data[AT_NORMAL+1]; - uint32 mask = 0x1; // vertices - if(geo->geoflags & Geometry::NORMALS) - mask |= 0x10; - if(geo->geoflags & Geometry::PRELIT) - mask |= 0x100; - if(geo->numTexCoordSets > 0) - mask |= 0x1000; - mask |= 0x10000; - - Vertex v; - for(uint32 i = 0; i < mesh->numIndices; i++){ - if(mask & 0x1) - memcpy(&v.p, verts, 12); - if(mask & 0x10){ - v.n[0] = norms[0]/127.0f; - v.n[1] = norms[1]/127.0f; - v.n[2] = norms[2]/127.0f; - } - if(mask & 0x100) - memcpy(&v.c, colors, 4); - if(mask & 0x1000) - memcpy(&v.t, texcoords, 8); - for(int j = 0; j < 4; j++){ - ((uint32*)v.w)[j] = wghts[j] & ~0x3FF; - v.i[j] = (wghts[j] & 0x3FF) >> 2; - if(v.i[j]) v.i[j]--; - if(v.w[j] == 0.0f) v.i[j] = 0; - } - int32 idx = findVertexSkin(geo, flags, mask, &v); - if(idx < 0) - idx = geo->numVertices++; - mesh->indices[i] = idx; - flags[idx] = mask; - insertVertexSkin(geo, idx, mask, &v); - verts += 3; - texcoords += 2; - colors += 4; - norms += 3; - wghts += 4; - } -} -*/ - -void -skinPreCB(MatPipeline*, Geometry *geo) -{ - Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); - if(skin == nil) - return; - uint8 *data = skin->data; - float *invMats = skin->inverseMatrices; - // meshHeader->totalIndices is highest possible number of vertices again - skin->init(skin->numBones, skin->numBones, geo->meshHeader->totalIndices); - memcpy(skin->inverseMatrices, invMats, skin->numBones*64); - delete[] data; -} - -void -skinPostCB(MatPipeline*, Geometry *geo) -{ - Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); - if(skin){ - skin->findNumWeights(geo->numVertices); - skin->findUsedBones(geo->numVertices); - } -} - // ADC int32 adcOffset; diff --git a/src/ps2/ps2matfx.cpp b/src/ps2/ps2matfx.cpp new file mode 100644 index 0000000..f81e855 --- /dev/null +++ b/src/ps2/ps2matfx.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwplugins.h" +#include "rwps2.h" +#include "rwps2plg.h" + +#define PLUGIN_ID ID_MATFX + +namespace rw { +namespace ps2 { + +static void* +matfxOpen(void *o, int32, int32) +{ + matFXGlobals.pipelines[PLATFORM_PS2] = makeMatFXPipeline(); + return o; +} + +static void* +matfxClose(void *o, int32, int32) +{ + return o; +} + +void +initMatFX(void) +{ + Driver::registerPlugin(PLATFORM_PS2, 0, ID_MATFX, + matfxOpen, matfxClose); +} + +ObjPipeline* +makeMatFXPipeline(void) +{ + MatPipeline *pipe = new MatPipeline(PLATFORM_PS2); + pipe->pluginID = ID_MATFX; + pipe->pluginData = 0; + pipe->attribs[AT_XYZ] = &attribXYZ; + pipe->attribs[AT_UV] = &attribUV; + pipe->attribs[AT_RGBA] = &attribRGBA; + pipe->attribs[AT_NORMAL] = &attribNormal; + uint32 vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3); + pipe->setTriBufferSizes(4, vertCount); + pipe->vifOffset = pipe->inputStride*vertCount; + pipe->uninstanceCB = genericUninstanceCB; + + ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2); + opipe->pluginID = ID_MATFX; + opipe->pluginData = 0; + opipe->groupPipeline = pipe; + return opipe; +} + +} +} diff --git a/src/ps2/ps2raster.cpp b/src/ps2/ps2raster.cpp index 6cba41b..9e9091b 100644 --- a/src/ps2/ps2raster.cpp +++ b/src/ps2/ps2raster.cpp @@ -61,15 +61,9 @@ ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh) } } -struct dword -{ - uint32 lo; - uint32 hi; -}; - #define ALIGN64(x) ((x) + 0x3F & ~0x3F) -static void +void rasterCreate(Raster *raster) { uint64 bufferWidth[7], bufferBase[7]; @@ -380,7 +374,7 @@ rasterCreate(Raster *raster) } } -static uint8* +uint8* rasterLock(Raster *raster, int32 level) { // TODO @@ -389,7 +383,7 @@ rasterLock(Raster *raster, int32 level) return nil; } -static void +void rasterUnlock(Raster *raster, int32 level) { // TODO @@ -397,7 +391,7 @@ rasterUnlock(Raster *raster, int32 level) (void)level; } -static int32 +int32 rasterNumLevels(Raster *raster) { Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); @@ -476,26 +470,9 @@ getSizeMipmap(void*, int32, int32) return rw::platform == PLATFORM_PS2 ? 4 : 0; } -static void* -nativeOpen(void*, int32, int32) -{ - driver[PLATFORM_PS2].rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_PS2].rasterCreate = rasterCreate; - driver[PLATFORM_PS2].rasterLock = rasterLock; - driver[PLATFORM_PS2].rasterUnlock = rasterUnlock; - driver[PLATFORM_PS2].rasterNumLevels = rasterNumLevels; -} - -static void* -nativeClose(void*, int32, int32) -{ - printf("ps2 native close\n"); -} - void registerNativeRaster(void) { - Engine::registerPlugin(0, ID_RASTERPS2, nativeOpen, nativeClose); nativeRasterOffset = Raster::registerPlugin(sizeof(Ps2Raster), ID_RASTERPS2, createNativeRaster, diff --git a/src/ps2/ps2skin.cpp b/src/ps2/ps2skin.cpp new file mode 100644 index 0000000..47b7455 --- /dev/null +++ b/src/ps2/ps2skin.cpp @@ -0,0 +1,329 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwplugins.h" +#include "rwps2.h" +#include "rwps2plg.h" + +#include "rwps2impl.h" + +#define PLUGIN_ID ID_SKIN + +namespace rw { +namespace ps2 { + +static void* +skinOpen(void *o, int32, int32) +{ + skinGlobals.pipelines[PLATFORM_PS2] = makeSkinPipeline(); + return o; +} + +static void* +skinClose(void *o, int32, int32) +{ + return o; +} + +void +initSkin(void) +{ + Driver::registerPlugin(PLATFORM_PS2, 0, ID_SKIN, + skinOpen, skinClose); +} + +ObjPipeline* +makeSkinPipeline(void) +{ + MatPipeline *pipe = new MatPipeline(PLATFORM_PS2); + pipe->pluginID = ID_SKIN; + pipe->pluginData = 1; + pipe->attribs[AT_XYZ] = &attribXYZ; + pipe->attribs[AT_UV] = &attribUV; + pipe->attribs[AT_RGBA] = &attribRGBA; + pipe->attribs[AT_NORMAL] = &attribNormal; + pipe->attribs[AT_NORMAL+1] = &attribWeights; + uint32 vertCount = MatPipeline::getVertCount(VU_Lights-0x100, 5, 3, 2); + pipe->setTriBufferSizes(5, vertCount); + pipe->vifOffset = pipe->inputStride*vertCount; + pipe->instanceCB = skinInstanceCB; + pipe->uninstanceCB = genericUninstanceCB; + pipe->preUninstCB = skinPreCB; + pipe->postUninstCB = skinPostCB; + + ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2); + opipe->pluginID = ID_SKIN; + opipe->pluginData = 1; + opipe->groupPipeline = pipe; + return opipe; +} + +Stream* +readNativeSkin(Stream *stream, int32, void *object, int32 offset) +{ + uint8 header[4]; + Geometry *geometry = (Geometry*)object; + uint32 platform; + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")) + return nil; + } + platform = stream->readU32(); + if(platform != PLATFORM_PS2){ + RWERROR((ERR_PLATFORM, platform)); + return nil; + } + stream->read(header, 4); + Skin *skin = new Skin; + *PLUGINOFFSET(Skin*, geometry, offset) = skin; + + // numUsedBones and numWeights appear in/after 34003 but not in/before 33002 + // (probably rw::version >= 0x34000) + bool oldFormat = header[1] == 0; + + // Use numBones for numUsedBones to allocate data + if(oldFormat) + skin->init(header[0], header[0], 0); + else + skin->init(header[0], header[1], 0); + skin->numWeights = header[2]; + + if(!oldFormat) + stream->read(skin->usedBones, skin->numUsedBones); + if(skin->numBones) + stream->read(skin->inverseMatrices, skin->numBones*64); + + // dummy data in case we need to write data in the new format + if(oldFormat){ + skin->numWeights = 4; + for(int32 i = 0; i < skin->numUsedBones; i++) + skin->usedBones[i] = i; + } + + if(!oldFormat) + // last 3 ints are split data as in the other formats + // TODO: what are the other 4? + stream->seek(7*4); + return stream; +} + +Stream* +writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset) +{ + uint8 header[4]; + + writeChunkHeader(stream, ID_STRUCT, len-12); + stream->writeU32(PLATFORM_PS2); + Skin *skin = *PLUGINOFFSET(Skin*, object, offset); + // not sure which version introduced the new format + bool oldFormat = version < 0x34000; + header[0] = skin->numBones; + if(oldFormat){ + header[1] = 0; + header[2] = 0; + }else{ + header[1] = skin->numUsedBones; + header[2] = skin->numWeights; + } + header[3] = 0; + stream->write(header, 4); + + if(!oldFormat) + stream->write(skin->usedBones, skin->numUsedBones); + stream->write(skin->inverseMatrices, skin->numBones*64); + if(!oldFormat){ + uint32 buffer[7] = { 0, 0, 0, 0, 0, 0, 0 }; + stream->write(buffer, 7*4); + } + return stream; +} + +int32 +getSizeNativeSkin(void *object, int32 offset) +{ + Skin *skin = *PLUGINOFFSET(Skin*, object, offset); + if(skin == nil) + return -1; + int32 size = 12 + 4 + 4 + skin->numBones*64; + // not sure which version introduced the new format + if(version >= 0x34000) + size += skin->numUsedBones + 16 + 12; + return size; +} + +void +instanceSkinData(Geometry*, Mesh *m, Skin *skin, uint32 *data) +{ + uint16 j; + float32 *weights = (float32*)data; + uint32 *indices = data; + for(uint32 i = 0; i < m->numIndices; i++){ + j = m->indices[i]; + for(int32 k = 0; k < 4; k++){ + *weights++ = skin->weights[j*4+k]; + *indices &= ~0x3FF; + *indices++ |= skin->indices[j*4+k] && skin->weights[j*4+k] ? + (skin->indices[j*4+k]+1) << 2 : 0; + } + } +} + +void +skinInstanceCB(MatPipeline *, Geometry *g, Mesh *m, uint8 **data) +{ + Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset); + if(skin == nil) + return; + instanceSkinData(g, m, skin, (uint32*)data[4]); +} + +// TODO: call base function perhaps? +int32 +findVertexSkin(Geometry *g, uint32 flags[], uint32 mask, Vertex *v) +{ + Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset); + float32 *wghts = nil; + uint8 *inds = nil; + if(skin){ + wghts = skin->weights; + inds = skin->indices; + } + + float32 *verts = g->morphTargets[0].vertices; + float32 *tex = g->texCoords[0]; + float32 *tex1 = g->texCoords[1]; + float32 *norms = g->morphTargets[0].normals; + uint8 *cols = g->colors; + + for(int32 i = 0; i < g->numVertices; i++){ + 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 & flag & 0x10 && + !(norms[0] == v->n[0] && norms[1] == v->n[1] && norms[2] == v->n[2])) + goto cont; + if(mask & flag & 0x100 && + !(cols[0] == v->c[0] && cols[1] == v->c[1] && cols[2] == v->c[2] && cols[3] == v->c[3])) + goto cont; + if(mask & flag & 0x1000 && + !(tex[0] == v->t[0] && tex[1] == v->t[1])) + goto cont; + if(mask & flag & 0x2000 && + !(tex1[0] == v->t1[0] && tex1[1] == v->t1[1])) + goto cont; + 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] && + inds[2] == v->i[2] && inds[3] == v->i[3])) + goto cont; + return i; + cont: + verts += 3; + tex += 2; + norms += 3; + cols += 4; + wghts += 4; + inds += 4; + } + return -1; +} + +void +insertVertexSkin(Geometry *geo, int32 i, uint32 mask, Vertex *v) +{ + Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); + insertVertex(geo, i, mask, v); + if(mask & 0x10000){ + memcpy(&skin->weights[i*4], v->w, 16); + memcpy(&skin->indices[i*4], v->i, 4); + } +} + +/* +void +skinUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[]) +{ + float32 *verts = (float32*)data[AT_XYZ]; + float32 *texcoords = (float32*)data[AT_UV]; + uint8 *colors = (uint8*)data[AT_RGBA]; + int8 *norms = (int8*)data[AT_NORMAL]; + uint32 *wghts = (uint32*)data[AT_NORMAL+1]; + uint32 mask = 0x1; // vertices + if(geo->geoflags & Geometry::NORMALS) + mask |= 0x10; + if(geo->geoflags & Geometry::PRELIT) + mask |= 0x100; + if(geo->numTexCoordSets > 0) + mask |= 0x1000; + mask |= 0x10000; + + Vertex v; + for(uint32 i = 0; i < mesh->numIndices; i++){ + if(mask & 0x1) + memcpy(&v.p, verts, 12); + if(mask & 0x10){ + v.n[0] = norms[0]/127.0f; + v.n[1] = norms[1]/127.0f; + v.n[2] = norms[2]/127.0f; + } + if(mask & 0x100) + memcpy(&v.c, colors, 4); + if(mask & 0x1000) + memcpy(&v.t, texcoords, 8); + for(int j = 0; j < 4; j++){ + ((uint32*)v.w)[j] = wghts[j] & ~0x3FF; + v.i[j] = (wghts[j] & 0x3FF) >> 2; + if(v.i[j]) v.i[j]--; + if(v.w[j] == 0.0f) v.i[j] = 0; + } + int32 idx = findVertexSkin(geo, flags, mask, &v); + if(idx < 0) + idx = geo->numVertices++; + mesh->indices[i] = idx; + flags[idx] = mask; + insertVertexSkin(geo, idx, mask, &v); + verts += 3; + texcoords += 2; + colors += 4; + norms += 3; + wghts += 4; + } +} +*/ + +void +skinPreCB(MatPipeline*, Geometry *geo) +{ + Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); + if(skin == nil) + return; + uint8 *data = skin->data; + float *invMats = skin->inverseMatrices; + // meshHeader->totalIndices is highest possible number of vertices again + skin->init(skin->numBones, skin->numBones, geo->meshHeader->totalIndices); + memcpy(skin->inverseMatrices, invMats, skin->numBones*64); + delete[] data; +} + +void +skinPostCB(MatPipeline*, Geometry *geo) +{ + Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); + if(skin){ + skin->findNumWeights(geo->numVertices); + skin->findUsedBones(geo->numVertices); + } +} + +} +} diff --git a/src/ps2/rwps2impl.h b/src/ps2/rwps2impl.h new file mode 100644 index 0000000..4b5944f --- /dev/null +++ b/src/ps2/rwps2impl.h @@ -0,0 +1,11 @@ +namespace rw { +namespace ps2 { + +void rasterCreate(Raster *raster); +uint8 *rasterLock(Raster*, int32 level); +void rasterUnlock(Raster*, int32); +int32 rasterNumLevels(Raster*); +void rasterFromImage(Raster *raster, Image *image); + +} +} diff --git a/src/ps2/rwps2plg.h b/src/ps2/rwps2plg.h index ac2d3be..8776a51 100644 --- a/src/ps2/rwps2plg.h +++ b/src/ps2/rwps2plg.h @@ -1,11 +1,16 @@ namespace rw { namespace ps2 { -ObjPipeline *makeSkinPipeline(void); +// MatFX plugin + +void initMatFX(void); ObjPipeline *makeMatFXPipeline(void); // Skin plugin +void initSkin(void); +ObjPipeline *makeSkinPipeline(void); + void insertVertexSkin(Geometry *geo, int32 i, uint32 mask, Vertex *v); int32 findVertexSkin(Geometry *g, uint32 flags[], uint32 mask, Vertex *v); diff --git a/src/rwengine.h b/src/rwengine.h index 8118899..328682c 100644 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -1,22 +1,18 @@ namespace rw { +// This is for platform independent things // TODO: move more stuff into this struct Engine { void *currentCamera; void *currentWorld; - static PluginList s_plglist; static void init(void); - static void open(void); - static int32 registerPlugin(int32 size, uint32 id, Constructor ctor, - Destructor dtor){ - return s_plglist.registerPlugin(size, id, ctor, dtor, nil); - } }; extern Engine *engine; +// This is for platform driver implementations struct Driver { ObjPipeline *defaultPipeline; @@ -30,9 +26,17 @@ struct Driver void (*rasterUnlock)(Raster*, int32 level); int32 (*rasterNumLevels)(Raster*); void (*rasterFromImage)(Raster*, Image*); + + static PluginList s_plglist[NUM_PLATFORMS]; + static void open(void); + static int32 registerPlugin(int32 platform, int32 size, uint32 id, + Constructor ctor, Destructor dtor){ + return s_plglist[platform].registerPlugin(size, id, + ctor, dtor, nil); + } }; -extern Driver driver[NUM_PLATFORMS]; +extern Driver *driver[NUM_PLATFORMS]; #define DRIVER driver[rw::platform] namespace null { diff --git a/src/rwplugins.h b/src/rwplugins.h index 63a9fa5..4e4229e 100644 --- a/src/rwplugins.h +++ b/src/rwplugins.h @@ -110,6 +110,7 @@ struct MatFX void setEffects(uint32 flags); static uint32 getEffects(Material *m); + static MatFX *get(Material *m); uint32 getEffectIndex(uint32 type); void setBumpTexture(Texture *t); void setBumpCoefficient(float32 coef); diff --git a/src/skin.cpp b/src/skin.cpp index a3df575..ab7d1d0 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -17,6 +17,7 @@ #include "d3d/rwd3d9.h" #include "gl/rwwdgl.h" #include "gl/rwgl3.h" +#include "gl/rwgl3plg.h" #define PLUGIN_ID ID_SKIN @@ -227,28 +228,6 @@ skinRights(void *object, int32, int32, uint32) Skin::setPipeline((Atomic*)object, 1); } -static void* -skinOpen(void*, int32, int32) -{ - skinGlobals.pipelines[PLATFORM_PS2] = - ps2::makeSkinPipeline(); - skinGlobals.pipelines[PLATFORM_XBOX] = - xbox::makeSkinPipeline(); - skinGlobals.pipelines[PLATFORM_D3D8] = - d3d8::makeSkinPipeline(); - skinGlobals.pipelines[PLATFORM_D3D9] = - d3d9::makeSkinPipeline(); - skinGlobals.pipelines[PLATFORM_WDGL] = - wdgl::makeSkinPipeline(); - skinGlobals.pipelines[PLATFORM_GL3] = - gl3::makeSkinPipeline(); -} - -static void* -skinClose(void*, int32, int32) -{ -} - void registerSkinPlugin(void) { @@ -259,10 +238,12 @@ registerSkinPlugin(void) for(uint i = 0; i < nelem(skinGlobals.pipelines); i++) skinGlobals.pipelines[i] = defpipe; - // TODO: call platform specific init functions? - // have platform specific open functions? - - Engine::registerPlugin(0, ID_SKIN, skinOpen, skinClose); + ps2::initSkin(); + xbox::initSkin(); + d3d8::initSkin(); + d3d9::initSkin(); + wdgl::initSkin(); + gl3::initSkin(); skinGlobals.offset = Geometry::registerPlugin(sizeof(Skin*), ID_SKIN, createSkin,