mirror of https://github.com/aap/librw.git
refactored skin plugin a bit; wrote xbox skin instance callback
This commit is contained in:
parent
f09a1ab99f
commit
0f135f2de6
38
src/ogl.cpp
38
src/ogl.cpp
|
@ -504,40 +504,19 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset)
|
|||
assert(stream->readU32() == PLATFORM_OGL);
|
||||
Skin *skin = new Skin;
|
||||
*PLUGINOFFSET(Skin*, geometry, offset) = skin;
|
||||
skin->numBones = stream->readI32();
|
||||
skin->numUsedBones = 0;
|
||||
skin->maxIndex = 0;
|
||||
|
||||
int32 size = skin->numBones*64 + 15;
|
||||
uint8 *data = new uint8[size];
|
||||
skin->data = data;
|
||||
skin->indices = NULL;
|
||||
skin->weights = NULL;
|
||||
skin->usedBones = NULL;
|
||||
|
||||
uintptr ptr = (uintptr)data + 15;
|
||||
ptr &= ~0xF;
|
||||
data = (uint8*)ptr;
|
||||
skin->inverseMatrices = NULL;
|
||||
if(skin->numBones){
|
||||
skin->inverseMatrices = (float*)data;
|
||||
stream->read(skin->inverseMatrices, skin->numBones*64);
|
||||
}
|
||||
int32 numBones = stream->readI32();
|
||||
skin->init(numBones, 0, 0);
|
||||
stream->read(skin->inverseMatrices, skin->numBones*64);
|
||||
}
|
||||
|
||||
void
|
||||
writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset)
|
||||
{
|
||||
uint8 header[4];
|
||||
|
||||
writeChunkHeader(stream, ID_STRUCT, len-12);
|
||||
stream->writeU32(PLATFORM_OGL);
|
||||
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
|
||||
header[0] = skin->numBones;
|
||||
header[1] = 0;
|
||||
header[2] = 0;
|
||||
header[3] = 0;
|
||||
stream->write(header, 4);
|
||||
stream->writeI32(skin->numBones);
|
||||
stream->write(skin->inverseMatrices, skin->numBones*64);
|
||||
}
|
||||
|
||||
|
@ -608,7 +587,11 @@ skinUninstanceCB(Geometry *geo)
|
|||
if(skin == NULL)
|
||||
return;
|
||||
|
||||
skin->allocateVertexData(geo->numVertices);
|
||||
uint8 *data = skin->data;
|
||||
float *invMats = skin->inverseMatrices;
|
||||
skin->init(skin->numBones, skin->numBones, geo->numVertices);
|
||||
memcpy(skin->inverseMatrices, invMats, skin->numBones*64);
|
||||
delete[] data;
|
||||
|
||||
uint8 *p;
|
||||
float *weights = skin->weights;
|
||||
|
@ -637,6 +620,9 @@ skinUninstanceCB(Geometry *geo)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
skin->findNumWeights(geo->numVertices);
|
||||
skin->findUsedBones(geo->numVertices);
|
||||
}
|
||||
|
||||
ObjPipeline*
|
||||
|
|
118
src/plugins.cpp
118
src/plugins.cpp
|
@ -362,8 +362,10 @@ static void*
|
|||
destroySkin(void *object, int32 offset, int32)
|
||||
{
|
||||
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
|
||||
if(skin)
|
||||
if(skin){
|
||||
delete[] skin->data;
|
||||
// delete[] skin->platformData;
|
||||
}
|
||||
delete skin;
|
||||
return object;
|
||||
}
|
||||
|
@ -381,10 +383,10 @@ copySkin(void *dst, void *src, int32 offset, int32)
|
|||
*PLUGINOFFSET(Skin*, dst, offset) = dstskin;
|
||||
dstskin->numBones = srcskin->numBones;
|
||||
dstskin->numUsedBones = srcskin->numUsedBones;
|
||||
dstskin->maxIndex = srcskin->maxIndex;
|
||||
dstskin->numWeights = srcskin->numWeights;
|
||||
|
||||
assert(0 && "can't copy skin yet");
|
||||
dstskin->allocateData(geometry->numVertices);
|
||||
dstskin->init(srcskin->numBones, srcskin->numUsedBones, geometry->numVertices);
|
||||
memcpy(dstskin->usedBones, srcskin->usedBones, srcskin->numUsedBones);
|
||||
memcpy(dstskin->inverseMatrices, srcskin->inverseMatrices,
|
||||
srcskin->numBones*64);
|
||||
|
@ -412,20 +414,22 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|||
return;
|
||||
}
|
||||
|
||||
stream->read(header, 4);
|
||||
stream->read(header, 4); // numBones, numUsedBones, numWeights, unused
|
||||
Skin *skin = new Skin;
|
||||
*PLUGINOFFSET(Skin*, geometry, offset) = skin;
|
||||
skin->numBones = header[0];
|
||||
|
||||
// both values unused in/before 33002, used in/after 34003
|
||||
// probably rw::version >= 0x34000
|
||||
skin->numUsedBones = header[1];
|
||||
skin->maxIndex = header[2];
|
||||
// numUsedBones and numWeights appear in/after 34003 but not in/before 33002
|
||||
// (probably rw::version >= 0x34000)
|
||||
bool oldFormat = header[1] == 0;
|
||||
|
||||
bool oldFormat = skin->numUsedBones == 0;
|
||||
skin->allocateData(geometry->numVertices);
|
||||
// Use numBones for numUsedBones to allocate data, find out the correct value later
|
||||
if(oldFormat)
|
||||
skin->init(header[0], header[0], geometry->numVertices);
|
||||
else
|
||||
skin->init(header[0], header[1], geometry->numVertices);
|
||||
skin->numWeights = header[2];
|
||||
|
||||
if(skin->usedBones)
|
||||
if(!oldFormat)
|
||||
stream->read(skin->usedBones, skin->numUsedBones);
|
||||
if(skin->indices)
|
||||
stream->read(skin->indices, geometry->numVertices*4);
|
||||
|
@ -437,6 +441,11 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|||
stream->read(&skin->inverseMatrices[i*16], 64);
|
||||
}
|
||||
|
||||
if(oldFormat){
|
||||
skin->findNumWeights(geometry->numVertices);
|
||||
skin->findUsedBones(geometry->numVertices);
|
||||
}
|
||||
|
||||
// no split skins in GTA
|
||||
if(!oldFormat)
|
||||
stream->seek(12);
|
||||
|
@ -461,15 +470,17 @@ writeSkin(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|||
}
|
||||
|
||||
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
|
||||
bool oldFormat = version < 0x34003;
|
||||
// not sure which version introduced the new format
|
||||
bool oldFormat = version < 0x34000;
|
||||
header[0] = skin->numBones;
|
||||
header[1] = skin->numUsedBones;
|
||||
header[2] = skin->maxIndex;
|
||||
header[3] = 0;
|
||||
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);
|
||||
|
@ -512,7 +523,7 @@ getSizeSkin(void *object, int32 offset, int32)
|
|||
int32 size = 4 + geometry->numVertices*(16+4) +
|
||||
skin->numBones*64;
|
||||
// not sure which version introduced the new format
|
||||
if(version < 0x34003)
|
||||
if(version < 0x34000)
|
||||
size += skin->numBones*4;
|
||||
else
|
||||
size += skin->numUsedBones + 12;
|
||||
|
@ -522,7 +533,7 @@ getSizeSkin(void *object, int32 offset, int32)
|
|||
static void
|
||||
skinRights(void *object, int32, int32, uint32)
|
||||
{
|
||||
((Atomic*)object)->pipeline = skinGlobals.pipelines[platformIdx[platform]];
|
||||
((Atomic*)object)->pipeline = skinGlobals.pipelines[platformIdx[rw::platform]];
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -553,53 +564,78 @@ registerSkinPlugin(void)
|
|||
}
|
||||
|
||||
void
|
||||
Skin::allocateData(int32 numVerts)
|
||||
Skin::init(int32 numBones, int32 numUsedBones, int32 numVertices)
|
||||
{
|
||||
this->numBones = numBones;
|
||||
this->numUsedBones = numUsedBones;
|
||||
uint32 size = this->numUsedBones +
|
||||
this->numBones*64 +
|
||||
numVerts*(16+4) + 15;
|
||||
numVertices*(16+4) + 0xF;
|
||||
this->data = new uint8[size];
|
||||
uint8 *data = this->data;
|
||||
uint8 *p = this->data;
|
||||
|
||||
this->usedBones = NULL;
|
||||
if(this->numUsedBones){
|
||||
this->usedBones = data;
|
||||
data += this->numUsedBones;
|
||||
this->usedBones = p;
|
||||
p += this->numUsedBones;
|
||||
}
|
||||
|
||||
uintptr ptr = (uintptr)data + 15;
|
||||
ptr &= ~0xF;
|
||||
data = (uint8*)ptr;
|
||||
p = (uint8*)(((uintptr)p + 0xF) & ~0xF);
|
||||
this->inverseMatrices = NULL;
|
||||
if(this->numBones){
|
||||
this->inverseMatrices = (float*)data;
|
||||
data += 64*this->numBones;
|
||||
this->inverseMatrices = (float*)p;
|
||||
p += 64*this->numBones;
|
||||
}
|
||||
|
||||
this->indices = NULL;
|
||||
if(numVerts){
|
||||
this->indices = data;
|
||||
data += 4*numVerts;
|
||||
if(numVertices){
|
||||
this->indices = p;
|
||||
p += 4*numVertices;
|
||||
}
|
||||
|
||||
this->weights = NULL;
|
||||
if(numVerts)
|
||||
this->weights = (float*)data;
|
||||
if(numVertices)
|
||||
this->weights = (float*)p;
|
||||
|
||||
this->platformData = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Skin::allocateVertexData(int32 numVerts)
|
||||
Skin::findNumWeights(int32 numVertices)
|
||||
{
|
||||
uint8 *usedBones = this->usedBones;
|
||||
float *invMats = this->inverseMatrices;
|
||||
uint8 *data = this->data;
|
||||
this->numWeights = 1;
|
||||
float *w = this->weights;
|
||||
while(numVertices--){
|
||||
while(w[this->numWeights] != 0.0f){
|
||||
this->numWeights++;
|
||||
if(this->numWeights == 4)
|
||||
return;
|
||||
}
|
||||
w += 4;
|
||||
}
|
||||
}
|
||||
|
||||
this->allocateData(numVerts);
|
||||
memcpy(this->usedBones, usedBones, this->numUsedBones);
|
||||
memcpy(this->inverseMatrices, invMats, this->numBones*64);
|
||||
delete[] data;
|
||||
void
|
||||
Skin::findUsedBones(int32 numVertices)
|
||||
{
|
||||
uint8 usedTab[256];
|
||||
uint8 *indices = this->indices;
|
||||
float *weights = this->weights;
|
||||
memset(usedTab, 0, 256);
|
||||
while(numVertices--){
|
||||
for(int32 i = 0; i < this->numWeights; i++){
|
||||
if(weights[i] == 0.0f)
|
||||
continue; // TODO: this could probably be optimized
|
||||
if(usedTab[indices[i]] == 0)
|
||||
usedTab[indices[i]]++;
|
||||
}
|
||||
indices += 4;
|
||||
weights += 4;
|
||||
}
|
||||
this->numUsedBones = 0;
|
||||
for(int32 i = 0; i < 256; i++)
|
||||
if(usedTab[i])
|
||||
this->usedBones[this->numUsedBones++] = i;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
55
src/ps2.cpp
55
src/ps2.cpp
|
@ -689,37 +689,32 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset)
|
|||
stream->read(header, 4);
|
||||
Skin *skin = new Skin;
|
||||
*PLUGINOFFSET(Skin*, geometry, offset) = skin;
|
||||
skin->numBones = header[0];
|
||||
|
||||
// both values unused in/before 33002, used in/after 34003
|
||||
skin->numUsedBones = header[1];
|
||||
skin->maxIndex = header[2];
|
||||
// numUsedBones and numWeights appear in/after 34003 but not in/before 33002
|
||||
// (probably rw::version >= 0x34000)
|
||||
bool oldFormat = header[1] == 0;
|
||||
|
||||
bool oldFormat = skin->numUsedBones == 0;
|
||||
int32 size = skin->numUsedBones + skin->numBones*64 + 15;
|
||||
uint8 *data = new uint8[size];
|
||||
skin->data = data;
|
||||
skin->indices = NULL;
|
||||
skin->weights = NULL;
|
||||
// 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];
|
||||
|
||||
skin->usedBones = NULL;
|
||||
if(skin->numUsedBones){
|
||||
skin->usedBones = data;
|
||||
data += skin->numUsedBones;
|
||||
stream->read(skin->data, skin->numUsedBones);
|
||||
}
|
||||
|
||||
uintptr ptr = (uintptr)data + 15;
|
||||
ptr &= ~0xF;
|
||||
data = (uint8*)ptr;
|
||||
skin->inverseMatrices = NULL;
|
||||
if(skin->numBones){
|
||||
skin->inverseMatrices = (float*)data;
|
||||
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 probably the same as in generic format
|
||||
// last 3 ints are split data as in the other formats
|
||||
// TODO: what are the other 4?
|
||||
stream->seek(7*4);
|
||||
}
|
||||
|
@ -732,15 +727,17 @@ writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset)
|
|||
writeChunkHeader(stream, ID_STRUCT, len-12);
|
||||
stream->writeU32(PLATFORM_PS2);
|
||||
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
|
||||
bool oldFormat = version < 0x34003;
|
||||
// not sure which version introduced the new format
|
||||
bool oldFormat = version < 0x34000;
|
||||
header[0] = skin->numBones;
|
||||
header[1] = skin->numUsedBones;
|
||||
header[2] = skin->maxIndex;
|
||||
header[3] = 0;
|
||||
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)
|
||||
|
@ -760,7 +757,7 @@ getSizeNativeSkin(void *object, int32 offset)
|
|||
return -1;
|
||||
int32 size = 12 + 4 + 4 + skin->numBones*64;
|
||||
// not sure which version introduced the new format
|
||||
if(version >= 0x34003)
|
||||
if(version >= 0x34000)
|
||||
size += skin->numUsedBones + 16 + 12;
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -314,7 +314,7 @@ struct Skin
|
|||
{
|
||||
int32 numBones;
|
||||
int32 numUsedBones;
|
||||
int32 maxIndex;
|
||||
int32 numWeights;
|
||||
uint8 *usedBones;
|
||||
float *inverseMatrices;
|
||||
uint8 *indices;
|
||||
|
@ -322,8 +322,9 @@ struct Skin
|
|||
uint8 *data; // only used by delete
|
||||
void *platformData; // a place to store platform specific stuff
|
||||
|
||||
void allocateData(int32 numVerts);
|
||||
void allocateVertexData(int32 numVerts);
|
||||
void init(int32 numBones, int32 numUsedBones, int32 numVertices);
|
||||
void findNumWeights(int32 numVertices);
|
||||
void findUsedBones(int32 numVertices);
|
||||
};
|
||||
|
||||
struct SkinGlobals
|
||||
|
|
69
src/xbox.cpp
69
src/xbox.cpp
|
@ -16,11 +16,6 @@ using namespace std;
|
|||
namespace rw {
|
||||
namespace xbox {
|
||||
|
||||
enum {
|
||||
D3DPT_TRIANGLELIST = 5,
|
||||
D3DPT_TRIANGLESTRIP = 6,
|
||||
};
|
||||
|
||||
void*
|
||||
destroyNativeData(void *object, int32, int32)
|
||||
{
|
||||
|
@ -149,6 +144,11 @@ ObjPipeline::ObjPipeline(uint32 platform)
|
|||
void
|
||||
ObjPipeline::instance(Atomic *atomic)
|
||||
{
|
||||
enum {
|
||||
D3DPT_TRIANGLELIST = 5,
|
||||
D3DPT_TRIANGLESTRIP = 6,
|
||||
};
|
||||
|
||||
Geometry *geo = atomic->geometry;
|
||||
if(geo->geoflags & Geometry::NATIVE)
|
||||
return;
|
||||
|
@ -281,18 +281,15 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset)
|
|||
assert(stream->readU32() == PLATFORM_XBOX);
|
||||
Skin *skin = new Skin;
|
||||
*PLUGINOFFSET(Skin*, geometry, offset) = skin;
|
||||
skin->numBones = stream->readI32();
|
||||
|
||||
// only allocate matrices
|
||||
skin->numUsedBones = 0;
|
||||
skin->allocateData(0);
|
||||
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));
|
||||
// we use our own variable for this due to allocation
|
||||
natskin->numUsedBones = stream->readI32();
|
||||
skin->maxIndex = stream->readI32();
|
||||
skin->numWeights = stream->readI32();
|
||||
stream->seek(4); // skip pointer to vertexBuffer
|
||||
natskin->stride = stream->readI32();
|
||||
int32 size = geometry->numVertices*natskin->stride;
|
||||
|
@ -319,7 +316,7 @@ writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset)
|
|||
stream->write(natskin->table1, 256*sizeof(int32));
|
||||
stream->write(natskin->table2, 256*sizeof(int32));
|
||||
stream->writeI32(natskin->numUsedBones);
|
||||
stream->writeI32(skin->maxIndex);
|
||||
stream->writeI32(skin->numWeights);
|
||||
stream->writeU32(0xBADEAFFE); // pointer to vertexBuffer
|
||||
stream->writeI32(natskin->stride);
|
||||
stream->write(natskin->vertexBuffer,
|
||||
|
@ -347,6 +344,54 @@ void
|
|||
skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
|
||||
{
|
||||
defaultInstanceCB(geo, header);
|
||||
|
||||
Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset);
|
||||
if(skin == NULL)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ObjPipeline*
|
||||
|
|
|
@ -13,7 +13,6 @@ using namespace rw;
|
|||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
rw::version = 0x33002;
|
||||
gta::registerEnvSpecPlugin();
|
||||
rw::registerMatFXPlugin();
|
||||
rw::registerMaterialRightsPlugin();
|
||||
|
@ -30,6 +29,7 @@ main(int argc, char *argv[])
|
|||
rw::registerMeshPlugin();
|
||||
rw::Atomic::init();
|
||||
|
||||
// rw::version = 0x33002;
|
||||
// rw::platform = rw::PLATFORM_PS2;
|
||||
// rw::platform = rw::PLATFORM_OGL;
|
||||
rw::platform = rw::PLATFORM_XBOX;
|
||||
|
|
Loading…
Reference in New Issue