mirror of
https://github.com/aap/librw.git
synced 2025-12-19 17:09:51 +00:00
revised initialization again and restructured code for that
This commit is contained in:
335
src/ps2/ps2.cpp
335
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;
|
||||
|
||||
64
src/ps2/ps2matfx.cpp
Normal file
64
src/ps2/ps2matfx.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
329
src/ps2/ps2skin.cpp
Normal file
329
src/ps2/ps2skin.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
11
src/ps2/rwps2impl.h
Normal file
11
src/ps2/rwps2impl.h
Normal file
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user