mirror of
https://github.com/aap/librw.git
synced 2025-01-23 09:11:34 +00:00
1382 lines
34 KiB
C++
1382 lines
34 KiB
C++
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <cassert>
|
|
|
|
#include <new>
|
|
|
|
#include "rwbase.h"
|
|
#include "rwplugin.h"
|
|
#include "rwpipeline.h"
|
|
#include "rwobjects.h"
|
|
#include "rwps2.h"
|
|
#include "rwd3d.h"
|
|
#include "rwxbox.h"
|
|
#include "gtaplg.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace rw {
|
|
|
|
int32
|
|
findPlatform(Clump *c)
|
|
{
|
|
FORLIST(lnk, c->atomics){
|
|
Geometry *g = Atomic::fromClump(lnk)->geometry;
|
|
if(g->instData)
|
|
return g->instData->platform;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
switchPipes(Clump *c, int32 platform)
|
|
{
|
|
FORLIST(lnk, c->atomics){
|
|
Atomic *a = Atomic::fromClump(lnk);
|
|
if(a->pipeline && a->pipeline->platform != platform){
|
|
uint32 plgid = a->pipeline->pluginID;
|
|
switch(plgid){
|
|
case ID_SKIN:
|
|
a->pipeline = skinGlobals.pipelines[platform];
|
|
break;
|
|
case ID_MATFX:
|
|
a->pipeline = matFXGlobals.pipelines[platform];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
namespace gta {
|
|
|
|
void
|
|
attachPlugins(void)
|
|
{
|
|
rw::ps2::registerPDSPlugin(12);
|
|
gta::registerPDSPipes();
|
|
|
|
rw::ps2::registerNativeRaster();
|
|
rw::xbox::registerNativeRaster();
|
|
rw::d3d::registerNativeRaster();
|
|
|
|
rw::registerMeshPlugin();
|
|
rw::registerNativeDataPlugin();
|
|
rw::registerAtomicRightsPlugin();
|
|
rw::registerMaterialRightsPlugin();
|
|
rw::xbox::registerVertexFormatPlugin();
|
|
rw::registerSkinPlugin();
|
|
rw::registerHAnimPlugin();
|
|
gta::registerNodeNamePlugin();
|
|
rw::registerMatFXPlugin();
|
|
rw::registerUVAnimPlugin();
|
|
rw::ps2::registerADCPlugin();
|
|
gta::registerExtraNormalsPlugin();
|
|
gta::registerExtraVertColorPlugin();
|
|
gta::registerEnvSpecPlugin();
|
|
gta::registerBreakableModelPlugin();
|
|
gta::registerCollisionPlugin();
|
|
gta::register2dEffectPlugin();
|
|
gta::registerPipelinePlugin();
|
|
|
|
rw::Atomic::init();
|
|
}
|
|
|
|
//
|
|
// Frame
|
|
//
|
|
|
|
// Node Name
|
|
|
|
int32 nodeNameOffset;
|
|
|
|
static void*
|
|
createNodeName(void *object, int32 offset, int32)
|
|
{
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
name[0] = '\0';
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
copyNodeName(void *dst, void *src, int32 offset, int32)
|
|
{
|
|
char *dstname = PLUGINOFFSET(char, dst, offset);
|
|
char *srcname = PLUGINOFFSET(char, src, offset);
|
|
strncpy(dstname, srcname, 23);
|
|
return dst;
|
|
}
|
|
|
|
static void*
|
|
destroyNodeName(void *object, int32, int32)
|
|
{
|
|
return object;
|
|
}
|
|
|
|
static void
|
|
readNodeName(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|
{
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
stream->read(name, len);
|
|
name[len] = '\0';
|
|
//printf("%s\n", name);
|
|
}
|
|
|
|
static void
|
|
writeNodeName(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|
{
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
stream->write(name, len);
|
|
}
|
|
|
|
static int32
|
|
getSizeNodeName(void *object, int32 offset, int32)
|
|
{
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
int32 len = strlen(name);
|
|
return len > 0 ? len : 0;
|
|
}
|
|
|
|
|
|
void
|
|
registerNodeNamePlugin(void)
|
|
{
|
|
nodeNameOffset = Frame::registerPlugin(24, ID_NODENAME,
|
|
createNodeName,
|
|
destroyNodeName,
|
|
copyNodeName);
|
|
Frame::registerPluginStream(ID_NODENAME,
|
|
readNodeName,
|
|
writeNodeName,
|
|
getSizeNodeName);
|
|
}
|
|
|
|
char*
|
|
getNodeName(Frame *f)
|
|
{
|
|
return PLUGINOFFSET(char, f, nodeNameOffset);
|
|
}
|
|
|
|
//
|
|
// Geometry
|
|
//
|
|
|
|
// Breakable Model
|
|
|
|
int32 breakableOffset;
|
|
|
|
static void*
|
|
createBreakableModel(void *object, int32 offset, int32)
|
|
{
|
|
*PLUGINOFFSET(uint8*, object, offset) = 0;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
destroyBreakableModel(void *object, int32 offset, int32)
|
|
{
|
|
uint8 *p = *PLUGINOFFSET(uint8*, object, offset);
|
|
delete[] p;
|
|
return object;
|
|
}
|
|
|
|
static void
|
|
readBreakableModel(Stream *stream, int32, void *object, int32 o, int32)
|
|
{
|
|
uint32 header[13];
|
|
uint32 hasBreakable = stream->readU32();
|
|
if(hasBreakable == 0)
|
|
return;
|
|
stream->read(header, 13*4);
|
|
uint32 size = header[1]*(12+8+4) + header[5]*(6+2) +
|
|
header[8]*(32+32+12);
|
|
uint8 *p = new uint8[sizeof(Breakable)+size];
|
|
Breakable *breakable = (Breakable*)p;
|
|
*PLUGINOFFSET(Breakable*, object, o) = breakable;
|
|
breakable->position = header[0];
|
|
breakable->numVertices = header[1];
|
|
breakable->numFaces = header[5];
|
|
breakable->numMaterials = header[8];
|
|
p += sizeof(Breakable);
|
|
stream->read(p, size);
|
|
breakable->vertices = (float*)p;
|
|
p += breakable->numVertices*12;
|
|
breakable->texCoords = (float*)p;
|
|
p += breakable->numVertices*8;
|
|
breakable->colors = (uint8*)p;
|
|
p += breakable->numVertices*4;
|
|
breakable->faces = (uint16*)p;
|
|
p += breakable->numFaces*6;
|
|
breakable->matIDs = (uint16*)p;
|
|
p += breakable->numFaces*2;
|
|
breakable->texNames = (char(*)[32])p;
|
|
p += breakable->numMaterials*32;
|
|
breakable->maskNames = (char(*)[32])p;
|
|
p += breakable->numMaterials*32;
|
|
breakable->surfaceProps = (float32(*)[3])p;
|
|
}
|
|
|
|
static void
|
|
writeBreakableModel(Stream *stream, int32, void *object, int32 o, int32)
|
|
{
|
|
uint32 header[13];
|
|
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o);
|
|
uint8 *p = (uint8*)breakable;
|
|
if(breakable == NULL){
|
|
stream->writeU32(0);
|
|
return;
|
|
}
|
|
stream->writeU32(1);
|
|
memset((char*)header, 0, 13*4);
|
|
header[0] = breakable->position;
|
|
header[1] = breakable->numVertices;
|
|
header[5] = breakable->numFaces;
|
|
header[8] = breakable->numMaterials;
|
|
stream->write(header, 13*4);
|
|
p += sizeof(Breakable);
|
|
stream->write(p, breakable->numVertices*(12+8+4) +
|
|
breakable->numFaces*(6+2) +
|
|
breakable->numMaterials*(32+32+12));
|
|
}
|
|
|
|
static int32
|
|
getSizeBreakableModel(void *object, int32 offset, int32)
|
|
{
|
|
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset);
|
|
if(breakable == NULL)
|
|
return 0; //4;
|
|
return 56 + breakable->numVertices*(12+8+4) +
|
|
breakable->numFaces*(6+2) +
|
|
breakable->numMaterials*(32+32+12);
|
|
}
|
|
|
|
void
|
|
registerBreakableModelPlugin(void)
|
|
{
|
|
breakableOffset = Geometry::registerPlugin(sizeof(Breakable*),
|
|
ID_BREAKABLE,
|
|
createBreakableModel,
|
|
destroyBreakableModel, NULL);
|
|
Geometry::registerPluginStream(ID_BREAKABLE,
|
|
readBreakableModel,
|
|
writeBreakableModel,
|
|
getSizeBreakableModel);
|
|
}
|
|
|
|
// Extra normals
|
|
|
|
int32 extraNormalsOffset;
|
|
|
|
static void*
|
|
createExtraNormals(void *object, int32 offset, int32)
|
|
{
|
|
*PLUGINOFFSET(float*, object, offset) = NULL;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
destroyExtraNormals(void *object, int32 offset, int32)
|
|
{
|
|
float *extranormals = *PLUGINOFFSET(float*, object, offset);
|
|
delete[] extranormals;
|
|
*PLUGINOFFSET(float*, object, offset) = NULL;
|
|
return object;
|
|
}
|
|
|
|
static void
|
|
readExtraNormals(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
Geometry *geo = (Geometry*)object;
|
|
float **plgp = PLUGINOFFSET(float*, object, offset);
|
|
if(*plgp)
|
|
delete[] *plgp;
|
|
float *extranormals = *plgp = new float[geo->numVertices*3];
|
|
stream->read(extranormals, geo->numVertices*3*4);
|
|
// printf("extra normals\n");
|
|
|
|
// for(int i = 0; i < geo->numVertices; i++){
|
|
// float *nx = extranormals+i*3;
|
|
// float *n = geo->morphTargets[0].normals;
|
|
// float len = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
|
|
// printf("%f %f %f %f\n", n[0], n[1], n[2], len);
|
|
// printf("%f %f %f\n", nx[0], nx[1], nx[2]);
|
|
// }
|
|
}
|
|
|
|
static void
|
|
writeExtraNormals(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
Geometry *geo = (Geometry*)object;
|
|
float *extranormals = *PLUGINOFFSET(float*, object, offset);
|
|
assert(extranormals != NULL);
|
|
stream->write(extranormals, geo->numVertices*3*4);
|
|
}
|
|
|
|
static int32
|
|
getSizeExtraNormals(void *object, int32 offset, int32)
|
|
{
|
|
Geometry *geo = (Geometry*)object;
|
|
if(*PLUGINOFFSET(float*, object, offset))
|
|
return geo->numVertices*3*4;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
registerExtraNormalsPlugin(void)
|
|
{
|
|
extraNormalsOffset = Geometry::registerPlugin(sizeof(void*),
|
|
ID_EXTRANORMALS,
|
|
createExtraNormals,
|
|
destroyExtraNormals,
|
|
NULL);
|
|
Geometry::registerPluginStream(ID_EXTRANORMALS,
|
|
readExtraNormals,
|
|
writeExtraNormals,
|
|
getSizeExtraNormals);
|
|
}
|
|
|
|
|
|
// Extra colors
|
|
|
|
int32 extraVertColorOffset;
|
|
|
|
void
|
|
allocateExtraVertColors(Geometry *g)
|
|
{
|
|
ExtraVertColors *colordata =
|
|
PLUGINOFFSET(ExtraVertColors, g, extraVertColorOffset);
|
|
colordata->nightColors = new uint8[g->numVertices*4];
|
|
colordata->dayColors = new uint8[g->numVertices*4];
|
|
colordata->balance = 1.0f;
|
|
}
|
|
|
|
static void*
|
|
createExtraVertColors(void *object, int32 offset, int32)
|
|
{
|
|
ExtraVertColors *colordata =
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
colordata->nightColors = NULL;
|
|
colordata->dayColors = NULL;
|
|
colordata->balance = 0.0f;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
destroyExtraVertColors(void *object, int32 offset, int32)
|
|
{
|
|
ExtraVertColors *colordata =
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
delete[] colordata->nightColors;
|
|
delete[] colordata->dayColors;
|
|
return object;
|
|
}
|
|
|
|
static void
|
|
readExtraVertColors(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
uint32 hasData;
|
|
ExtraVertColors *colordata =
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
hasData = stream->readU32();
|
|
if(!hasData)
|
|
return;
|
|
Geometry *geometry = (Geometry*)object;
|
|
colordata->nightColors = new uint8[geometry->numVertices*4];
|
|
colordata->dayColors = new uint8[geometry->numVertices*4];
|
|
colordata->balance = 1.0f;
|
|
stream->read(colordata->nightColors, geometry->numVertices*4);
|
|
if(geometry->colors)
|
|
memcpy(colordata->dayColors, geometry->colors,
|
|
geometry->numVertices*4);
|
|
}
|
|
|
|
static void
|
|
writeExtraVertColors(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
ExtraVertColors *colordata =
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
stream->writeU32(colordata->nightColors != NULL);
|
|
if(colordata->nightColors){
|
|
Geometry *geometry = (Geometry*)object;
|
|
stream->write(colordata->nightColors, geometry->numVertices*4);
|
|
}
|
|
}
|
|
|
|
static int32
|
|
getSizeExtraVertColors(void *object, int32 offset, int32)
|
|
{
|
|
ExtraVertColors *colordata =
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
Geometry *geometry = (Geometry*)object;
|
|
if(colordata->nightColors)
|
|
return 4 + geometry->numVertices*4;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
registerExtraVertColorPlugin(void)
|
|
{
|
|
extraVertColorOffset = Geometry::registerPlugin(sizeof(ExtraVertColors),
|
|
ID_EXTRAVERTCOLORS,
|
|
createExtraVertColors,
|
|
destroyExtraVertColors,
|
|
NULL);
|
|
Geometry::registerPluginStream(ID_EXTRAVERTCOLORS,
|
|
readExtraVertColors,
|
|
writeExtraVertColors,
|
|
getSizeExtraVertColors);
|
|
}
|
|
|
|
// Environment mat
|
|
|
|
int32 envMatOffset;
|
|
|
|
static void*
|
|
createEnvMat(void *object, int32 offset, int32)
|
|
{
|
|
*PLUGINOFFSET(EnvMat*, object, offset) = NULL;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
destroyEnvMat(void *object, int32 offset, int32)
|
|
{
|
|
EnvMat **envmat = PLUGINOFFSET(EnvMat*, object, offset);
|
|
delete *envmat;
|
|
*envmat = NULL;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
copyEnvMat(void *dst, void *src, int32 offset, int32)
|
|
{
|
|
EnvMat *srcenv = *PLUGINOFFSET(EnvMat*, src, offset);
|
|
if(srcenv == NULL)
|
|
return dst;
|
|
EnvMat *dstenv = new EnvMat;
|
|
dstenv->scaleX = srcenv->scaleX;
|
|
dstenv->scaleY = srcenv->scaleY;
|
|
dstenv->transScaleX = srcenv->transScaleX;
|
|
dstenv->transScaleY = srcenv->transScaleY;
|
|
dstenv->shininess = srcenv->shininess;
|
|
dstenv->texture = NULL;
|
|
*PLUGINOFFSET(EnvMat*, dst, offset) = dstenv;
|
|
return dst;
|
|
}
|
|
|
|
struct EnvStream {
|
|
float scaleX, scaleY;
|
|
float transScaleX, transScaleY;
|
|
float shininess;
|
|
int32 zero;
|
|
};
|
|
|
|
static void
|
|
readEnvMat(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
EnvStream buf;
|
|
EnvMat *env = new EnvMat;
|
|
*PLUGINOFFSET(EnvMat*, object, offset) = env;
|
|
stream->read(&buf, sizeof(buf));
|
|
env->scaleX = (int8)(buf.scaleX*8.0f);
|
|
env->scaleY = (int8)(buf.scaleY*8.0f);
|
|
env->transScaleX = (int8)(buf.transScaleX*8.0f);
|
|
env->transScaleY = (int8)(buf.transScaleY*8.0f);
|
|
env->shininess = (int8)(buf.shininess*255.0f);
|
|
env->texture = NULL;
|
|
}
|
|
|
|
static void
|
|
writeEnvMat(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
EnvStream buf;
|
|
EnvMat *env = *PLUGINOFFSET(EnvMat*, object, offset);
|
|
buf.scaleX = env->scaleX/8.0f;
|
|
buf.scaleY = env->scaleY/8.0f;
|
|
buf.transScaleX = env->transScaleX/8.0f;
|
|
buf.transScaleY = env->transScaleY/8.0f;
|
|
buf.shininess = env->shininess/8.0f;
|
|
buf.zero = 0;
|
|
stream->write(&buf, sizeof(buf));
|
|
}
|
|
|
|
static int32
|
|
getSizeEnvMat(void *object, int32 offset, int32)
|
|
{
|
|
EnvMat *env = *PLUGINOFFSET(EnvMat*, object, offset);
|
|
return env ? (int)sizeof(EnvStream) : 0;
|
|
}
|
|
|
|
// Specular mat
|
|
|
|
int32 specMatOffset;
|
|
|
|
static void*
|
|
createSpecMat(void *object, int32 offset, int32)
|
|
{
|
|
*PLUGINOFFSET(SpecMat*, object, offset) = NULL;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
destroySpecMat(void *object, int32 offset, int32)
|
|
{
|
|
SpecMat **specmat = PLUGINOFFSET(SpecMat*, object, offset);
|
|
if(*specmat == NULL)
|
|
return object;
|
|
if((*specmat)->texture)
|
|
(*specmat)->texture->destroy();
|
|
delete *specmat;
|
|
*specmat = NULL;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
copySpecMat(void *dst, void *src, int32 offset, int32)
|
|
{
|
|
SpecMat *srcspec = *PLUGINOFFSET(SpecMat*, src, offset);
|
|
if(srcspec == NULL)
|
|
return dst;
|
|
SpecMat *dstspec = new SpecMat;
|
|
*PLUGINOFFSET(SpecMat*, dst, offset) = dstspec;
|
|
dstspec->specularity = srcspec->specularity;
|
|
dstspec->texture = srcspec->texture;
|
|
dstspec->texture->refCount++;
|
|
return dst;
|
|
}
|
|
|
|
struct SpecStream {
|
|
float specularity;
|
|
char texname[24];
|
|
};
|
|
|
|
static void
|
|
readSpecMat(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
SpecStream buf;
|
|
SpecMat *spec = new SpecMat;
|
|
*PLUGINOFFSET(SpecMat*, object, offset) = spec;
|
|
stream->read(&buf, sizeof(buf));
|
|
spec->specularity = buf.specularity;
|
|
spec->texture = Texture::create(NULL);
|
|
strncpy(spec->texture->name, buf.texname, 24);
|
|
}
|
|
|
|
static void
|
|
writeSpecMat(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
SpecStream buf;
|
|
SpecMat *spec = *PLUGINOFFSET(SpecMat*, object, offset);
|
|
buf.specularity = spec->specularity;
|
|
strncpy(buf.texname, spec->texture->name, 24);
|
|
stream->write(&buf, sizeof(buf));
|
|
}
|
|
|
|
static int32
|
|
getSizeSpecMat(void *object, int32 offset, int32)
|
|
{
|
|
SpecMat *spec = *PLUGINOFFSET(SpecMat*, object, offset);
|
|
return spec ? (int)sizeof(SpecStream) : 0;
|
|
}
|
|
|
|
void
|
|
registerEnvSpecPlugin(void)
|
|
{
|
|
envMatOffset = Material::registerPlugin(sizeof(EnvMat*), ID_ENVMAT,
|
|
createEnvMat,
|
|
destroyEnvMat,
|
|
copyEnvMat);
|
|
Material::registerPluginStream(ID_ENVMAT, readEnvMat,
|
|
writeEnvMat,
|
|
getSizeEnvMat);
|
|
specMatOffset = Material::registerPlugin(sizeof(SpecMat*), ID_SPECMAT,
|
|
createSpecMat,
|
|
destroySpecMat,
|
|
copySpecMat);
|
|
Material::registerPluginStream(ID_SPECMAT, readSpecMat,
|
|
writeSpecMat,
|
|
getSizeSpecMat);
|
|
}
|
|
|
|
// Pipeline
|
|
|
|
int32 pipelineOffset;
|
|
|
|
static void*
|
|
createPipeline(void *object, int32 offset, int32)
|
|
{
|
|
*PLUGINOFFSET(uint32, object, offset) = 0;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
copyPipeline(void *dst, void *src, int32 offset, int32)
|
|
{
|
|
*PLUGINOFFSET(uint32, dst, offset) = *PLUGINOFFSET(uint32, src, offset);
|
|
return dst;
|
|
}
|
|
|
|
static void
|
|
readPipeline(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
*PLUGINOFFSET(uint32, object, offset) = stream->readU32();
|
|
// printf("%x\n", *PLUGINOFFSET(uint32, object, offset));
|
|
}
|
|
|
|
static void
|
|
writePipeline(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
stream->writeU32(*PLUGINOFFSET(uint32, object, offset));
|
|
}
|
|
|
|
static int32
|
|
getSizePipeline(void *object, int32 offset, int32)
|
|
{
|
|
if(*PLUGINOFFSET(uint32, object, offset))
|
|
return 4;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
registerPipelinePlugin(void)
|
|
{
|
|
pipelineOffset = Atomic::registerPlugin(sizeof(uint32), ID_PIPELINE,
|
|
createPipeline,
|
|
NULL,
|
|
copyPipeline);
|
|
Atomic::registerPluginStream(ID_PIPELINE, readPipeline,
|
|
writePipeline, getSizePipeline);
|
|
}
|
|
|
|
uint32
|
|
getPipelineID(Atomic *atomic)
|
|
{
|
|
return *PLUGINOFFSET(uint32, atomic, pipelineOffset);
|
|
}
|
|
|
|
void
|
|
setPipelineID(Atomic *atomic, uint32 id)
|
|
{
|
|
*PLUGINOFFSET(uint32, atomic, pipelineOffset) = id;
|
|
}
|
|
|
|
// 2dEffect
|
|
|
|
struct SizedData
|
|
{
|
|
uint32 size;
|
|
uint8 *data;
|
|
};
|
|
|
|
int32 twodEffectOffset;
|
|
|
|
static void*
|
|
create2dEffect(void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data;
|
|
data = PLUGINOFFSET(SizedData, object, offset);
|
|
data->size = 0;
|
|
data->data = NULL;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
destroy2dEffect(void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data;
|
|
data = PLUGINOFFSET(SizedData, object, offset);
|
|
delete[] data->data;
|
|
data->data = NULL;
|
|
data->size = 0;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
copy2dEffect(void *dst, void *src, int32 offset, int32)
|
|
{
|
|
SizedData *srcdata, *dstdata;
|
|
dstdata = PLUGINOFFSET(SizedData, dst, offset);
|
|
srcdata = PLUGINOFFSET(SizedData, src, offset);
|
|
dstdata->size = srcdata->size;
|
|
if(dstdata->size != 0){
|
|
dstdata->data = new uint8[dstdata->size];
|
|
memcpy(dstdata->data, srcdata->data, dstdata->size);
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
static void
|
|
read2dEffect(Stream *stream, int32 size, void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data = PLUGINOFFSET(SizedData, object, offset);
|
|
data->size = size;
|
|
data->data = new uint8[data->size];
|
|
stream->read(data->data, data->size);
|
|
}
|
|
|
|
static void
|
|
write2dEffect(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data = PLUGINOFFSET(SizedData, object, offset);
|
|
stream->write(data->data, data->size);
|
|
}
|
|
|
|
static int32
|
|
getSize2dEffect(void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data = PLUGINOFFSET(SizedData, object, offset);
|
|
return data->size;
|
|
}
|
|
|
|
void
|
|
register2dEffectPlugin(void)
|
|
{
|
|
twodEffectOffset = Geometry::registerPlugin(sizeof(SizedData), ID_2DEFFECT,
|
|
create2dEffect,
|
|
destroy2dEffect,
|
|
copy2dEffect);
|
|
Geometry::registerPluginStream(ID_2DEFFECT, read2dEffect,
|
|
write2dEffect, getSize2dEffect);
|
|
}
|
|
|
|
// Collision
|
|
|
|
int32 collisionOffset;
|
|
|
|
static void*
|
|
createCollision(void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data;
|
|
data = PLUGINOFFSET(SizedData, object, offset);
|
|
data->size = 0;
|
|
data->data = NULL;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
destroyCollision(void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data;
|
|
data = PLUGINOFFSET(SizedData, object, offset);
|
|
delete[] data->data;
|
|
data->data = NULL;
|
|
data->size = 0;
|
|
return object;
|
|
}
|
|
|
|
static void*
|
|
copyCollision(void *dst, void *src, int32 offset, int32)
|
|
{
|
|
SizedData *srcdata, *dstdata;
|
|
dstdata = PLUGINOFFSET(SizedData, dst, offset);
|
|
srcdata = PLUGINOFFSET(SizedData, src, offset);
|
|
dstdata->size = srcdata->size;
|
|
if(dstdata->size != 0){
|
|
dstdata->data = new uint8[dstdata->size];
|
|
memcpy(dstdata->data, srcdata->data, dstdata->size);
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
static void
|
|
readCollision(Stream *stream, int32 size, void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data = PLUGINOFFSET(SizedData, object, offset);
|
|
data->size = size;
|
|
data->data = new uint8[data->size];
|
|
stream->read(data->data, data->size);
|
|
}
|
|
|
|
static void
|
|
writeCollision(Stream *stream, int32, void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data = PLUGINOFFSET(SizedData, object, offset);
|
|
stream->write(data->data, data->size);
|
|
}
|
|
|
|
static int32
|
|
getSizeCollision(void *object, int32 offset, int32)
|
|
{
|
|
SizedData *data = PLUGINOFFSET(SizedData, object, offset);
|
|
return data->size;
|
|
}
|
|
|
|
void
|
|
registerCollisionPlugin(void)
|
|
{
|
|
collisionOffset = Clump::registerPlugin(sizeof(SizedData), ID_COLLISION,
|
|
createCollision,
|
|
destroyCollision,
|
|
copyCollision);
|
|
Clump::registerPluginStream(ID_COLLISION, readCollision,
|
|
writeCollision, getSizeCollision);
|
|
}
|
|
|
|
/*
|
|
* PS2
|
|
*/
|
|
|
|
using namespace ps2;
|
|
|
|
rw::PipeAttribute saXYZADC = {
|
|
"saXYZADC",
|
|
AT_V4_16 | AT_RW
|
|
};
|
|
|
|
rw::PipeAttribute saUV = {
|
|
"saUV",
|
|
AT_V2_16 | AT_RW
|
|
};
|
|
|
|
rw::PipeAttribute saUV2 = {
|
|
"saUV2",
|
|
AT_V4_16 | AT_RW
|
|
};
|
|
|
|
rw::PipeAttribute saRGBA = {
|
|
"saRGBA",
|
|
AT_V4_8 | AT_UNSGN | AT_RW
|
|
};
|
|
|
|
rw::PipeAttribute saRGBA2 = {
|
|
"saRGBA2",
|
|
AT_V4_16 | AT_UNSGN | AT_RW
|
|
};
|
|
|
|
rw::PipeAttribute saNormal = {
|
|
"saNormal",
|
|
AT_V4_8 | AT_RW
|
|
};
|
|
|
|
rw::PipeAttribute saWeights = {
|
|
"saWeights",
|
|
AT_V4_32 | AT_RW
|
|
};
|
|
|
|
static bool hasTex2(uint32 id)
|
|
{
|
|
return id == 0x53f2008b;
|
|
}
|
|
static bool hasNormals(uint32 id)
|
|
{
|
|
return id == 0x53f20085 || id == 0x53f20087 || id == 0x53f20089 ||
|
|
id == 0x53f2008b || id == 0x53f2008d || id == 0x53f2008f;
|
|
}
|
|
static bool hasColors(uint32 id)
|
|
{
|
|
return id == 0x53f20081 || id == 0x53f20083 || id == 0x53f2008d || id == 0x53f2008f;
|
|
}
|
|
static bool hasColors2(uint32 id)
|
|
{
|
|
return id == 0x53f20083 || id == 0x53f2008f;
|
|
}
|
|
|
|
struct SaVert : ps2::Vertex {
|
|
float32 w[4];
|
|
uint8 i[4];
|
|
float32 t1[2];
|
|
uint8 c1[4];
|
|
};
|
|
|
|
static void
|
|
saPreCB(MatPipeline *p, Geometry *geo)
|
|
{
|
|
allocateADC(geo);
|
|
if(hasColors2(p->pluginData) && extraVertColorOffset)
|
|
allocateExtraVertColors(geo);
|
|
if(p->pluginData == 0x53f20089)
|
|
skinPreCB(p, geo);
|
|
}
|
|
|
|
static void
|
|
saPostCB(MatPipeline *p, Geometry *geo)
|
|
{
|
|
skinPostCB(p, geo);
|
|
}
|
|
|
|
int32
|
|
findSAVertex(Geometry *g, uint32 flags[], uint32 mask, SaVert *v)
|
|
{
|
|
Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset);
|
|
float32 *wghts = NULL;
|
|
uint8 *inds = NULL;
|
|
if(skin){
|
|
wghts = skin->weights;
|
|
inds = skin->indices;
|
|
}
|
|
float32 *verts = g->morphTargets[0].vertices;
|
|
float32 *tex0 = g->texCoords[0];
|
|
float32 *tex1 = g->texCoords[1];
|
|
float32 *norms = g->morphTargets[0].normals;
|
|
uint8 *cols0 = g->colors;
|
|
uint8 *cols1 = NULL;
|
|
if(extraVertColorOffset)
|
|
cols1 = PLUGINOFFSET(ExtraVertColors, g, extraVertColorOffset)->nightColors;
|
|
|
|
for(int32 i = 0; i < g->numVertices; i++){
|
|
if(mask & flags[i] & 0x1 &&
|
|
!(verts[0] == v->p[0] && verts[1] == v->p[1] && verts[2] == v->p[2]))
|
|
goto cont;
|
|
if(mask & flags[i] & 0x10 &&
|
|
!(norms[0] == v->n[0] && norms[1] == v->n[1] && norms[2] == v->n[2]))
|
|
goto cont;
|
|
if(mask & flags[i] & 0x100 &&
|
|
!(cols0[0] == v->c[0] && cols0[1] == v->c[1] &&
|
|
cols0[2] == v->c[2] && cols0[3] == v->c[3]))
|
|
goto cont;
|
|
if(mask & flags[i] & 0x200 &&
|
|
!(cols1[0] == v->c1[0] && cols1[1] == v->c1[1] &&
|
|
cols1[2] == v->c1[2] && cols1[3] == v->c1[3]))
|
|
goto cont;
|
|
if(mask & flags[i] & 0x1000 &&
|
|
!(tex0[0] == v->t[0] && tex0[1] == v->t[1]))
|
|
goto cont;
|
|
if(mask & flags[i] & 0x2000 &&
|
|
!(tex1[0] == v->t1[0] && tex1[1] == v->t1[1]))
|
|
goto cont;
|
|
if(mask & flags[i] & 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;
|
|
tex0 += 2;
|
|
tex1 += 2;
|
|
norms += 3;
|
|
cols0 += 4;
|
|
cols1 += 4;
|
|
wghts += 4;
|
|
inds += 4;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void
|
|
insertSAVertex(Geometry *geo, int32 i, uint32 mask, SaVert *v)
|
|
{
|
|
insertVertex(geo, i, mask, v);
|
|
if(mask & 0x2000)
|
|
memcpy(&geo->texCoords[1][i*2], v->t1, 8);
|
|
if(mask & 0x200 && extraVertColorOffset){
|
|
uint8 *cols1 =
|
|
&PLUGINOFFSET(ExtraVertColors, geo, extraVertColorOffset)->nightColors[i*4];
|
|
cols1[0] = v->c1[0];
|
|
cols1[1] = v->c1[1];
|
|
cols1[2] = v->c1[2];
|
|
cols1[3] = v->c1[3];
|
|
}
|
|
if(mask & 0x10000 && skinGlobals.offset){
|
|
Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset);
|
|
memcpy(&skin->weights[i*4], v->w, 16);
|
|
memcpy(&skin->indices[i*4], v->i, 4);
|
|
}
|
|
}
|
|
|
|
static void
|
|
saUninstanceCB(ps2::MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[])
|
|
{
|
|
uint32 id = pipe->pluginData;
|
|
int16 *verts = (int16*)data[0];
|
|
int16 *texcoords = (int16*)data[1];
|
|
uint8 *colors = (uint8*)data[2];
|
|
int8 *norms = (int8*)data[id == 0x53f20089 ? 2 : 3];
|
|
uint32 *wghts = (uint32*)data[3];
|
|
float vertScale = 1.0f/128.0f;
|
|
if(id == 0x53f20085 || id == 0x53f20087 ||
|
|
id == 0x53f20089 || id == 0x53f2008b)
|
|
vertScale = 1.0f/1024.0f;
|
|
uint32 mask = 0x1; // vertices
|
|
int cinc = 4;
|
|
int tinc = 2;
|
|
if((geo->geoflags & Geometry::NORMALS) && hasNormals(id))
|
|
mask |= 0x10;
|
|
if((geo->geoflags & Geometry::PRELIT) && hasColors(id))
|
|
mask |= 0x100;
|
|
if(hasColors2(id)){
|
|
mask |= 0x200;
|
|
cinc *= 2;
|
|
}
|
|
if(geo->numTexCoordSets > 0)
|
|
mask |= 0x1000;
|
|
if(geo->numTexCoordSets > 0 && hasTex2(id)){
|
|
mask |= 0x2000;
|
|
tinc *= 2;
|
|
}
|
|
if(id == 0x53f20089)
|
|
mask |= 0x10000;
|
|
SaVert v;
|
|
int32 idxstart = 0;
|
|
for(Mesh *m = geo->meshHeader->mesh; m < mesh; m++)
|
|
idxstart += m->numIndices;
|
|
int8 *adc = PLUGINOFFSET(ADCData, geo, adcOffset)->adcBits;
|
|
for(uint32 i = 0; i < mesh->numIndices; i++){
|
|
v.p[0] = verts[0]*vertScale;
|
|
v.p[1] = verts[1]*vertScale;
|
|
v.p[2] = verts[2]*vertScale;
|
|
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 & 0x200){
|
|
v.c[0] = colors[0];
|
|
v.c[1] = colors[2];
|
|
v.c[2] = colors[4];
|
|
v.c[3] = colors[6];
|
|
v.c1[0] = colors[1];
|
|
v.c1[1] = colors[3];
|
|
v.c1[2] = colors[5];
|
|
v.c1[3] = colors[7];
|
|
}else if(mask & 0x100){
|
|
v.c[0] = colors[0];
|
|
v.c[1] = colors[1];
|
|
v.c[2] = colors[2];
|
|
v.c[3] = colors[3];
|
|
}
|
|
if(mask & 0x1000){
|
|
v.t[0] = texcoords[0]/4096.0f;
|
|
v.t[1] = texcoords[1]/4096.0f;
|
|
}
|
|
if(mask & 0x2000){
|
|
v.t1[0] = texcoords[2]/4096.0f;
|
|
v.t1[1] = texcoords[3]/4096.0f;
|
|
}
|
|
if(mask & 0x10000){
|
|
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 = findSAVertex(geo, flags, mask, &v);
|
|
if(idx < 0)
|
|
idx = geo->numVertices++;
|
|
mesh->indices[i] = idx;
|
|
adc[idxstart+i] = !!verts[3];
|
|
flags[idx] = mask;
|
|
insertSAVertex(geo, idx, mask, &v);
|
|
|
|
verts += 4;
|
|
texcoords += tinc;
|
|
colors += cinc;
|
|
norms += 4;
|
|
wghts += 4;
|
|
}
|
|
}
|
|
|
|
static void
|
|
instanceSAPositions(Geometry *g, Mesh *m, int8 *adc, int16 *dst, float32 scale)
|
|
{
|
|
float32 *verts = g->morphTargets[0].vertices;
|
|
uint16 j;
|
|
for(uint32 i = 0; i < m->numIndices; i++){
|
|
j = m->indices[i];
|
|
dst[0] = verts[j*3+0]*scale;
|
|
dst[1] = verts[j*3+1]*scale;
|
|
dst[2] = verts[j*3+2]*scale;
|
|
dst[3] = adc ? 0x8000*adc[i] : 0;
|
|
dst += 4;
|
|
}
|
|
}
|
|
|
|
static void
|
|
instanceSATex(Geometry *g, Mesh *m, int16 *dst)
|
|
{
|
|
float32 *tex = g->texCoords[0];
|
|
uint16 j;
|
|
for(uint32 i = 0; i < m->numIndices; i++){
|
|
j = m->indices[i];
|
|
if(tex){
|
|
dst[0] = tex[j*2+0]*4096.0f;
|
|
dst[1] = tex[j*2+1]*4096.0f;
|
|
}else{
|
|
dst[0] = 0;
|
|
dst[1] = 0;
|
|
}
|
|
dst += 2;
|
|
}
|
|
}
|
|
|
|
static void
|
|
instanceSADualTex(Geometry *g, Mesh *m, int16 *dst)
|
|
{
|
|
float32 *tex0 = g->texCoords[0];
|
|
float32 *tex1 = g->texCoords[1];
|
|
uint16 j;
|
|
for(uint32 i = 0; i < m->numIndices; i++){
|
|
j = m->indices[i];
|
|
if(tex0){
|
|
dst[0] = tex0[j*2+0]*4096.0f;
|
|
dst[1] = tex0[j*2+1]*4096.0f;
|
|
}else{
|
|
dst[0] = 0;
|
|
dst[1] = 0;
|
|
}
|
|
if(tex1){
|
|
dst[2] = tex1[j*2+0]*4096.0f;
|
|
dst[3] = tex1[j*2+1]*4096.0f;
|
|
}else{
|
|
dst[2] = 0;
|
|
dst[3] = 0;
|
|
}
|
|
dst += 4;
|
|
}
|
|
}
|
|
|
|
static void
|
|
instanceSAColors(Geometry *g, Mesh *m, uint8 *dst)
|
|
{
|
|
uint8 *c = g->colors;
|
|
uint16 j;
|
|
for(uint32 i = 0; i < m->numIndices; i++){
|
|
j = m->indices[i];
|
|
if(c)
|
|
memcpy(dst, &c[j*4], 4);
|
|
else
|
|
memset(dst, 0xFF, 4);
|
|
dst += 4;
|
|
}
|
|
}
|
|
|
|
static void
|
|
instanceSADualColors(Geometry *g, Mesh *m, uint8 *dst)
|
|
{
|
|
uint8 *c0 = g->colors;
|
|
uint8 *c1 =
|
|
PLUGINOFFSET(ExtraVertColors, g, extraVertColorOffset)->nightColors;
|
|
uint16 j;
|
|
for(uint32 i = 0; i < m->numIndices; i++){
|
|
j = m->indices[i];
|
|
if(c0){
|
|
dst[0] = c0[j*4+0];
|
|
dst[2] = c0[j*4+1];
|
|
dst[4] = c0[j*4+2];
|
|
dst[6] = c0[j*4+3];
|
|
}else{
|
|
dst[0] = 0xFF;
|
|
dst[2] = 0xFF;
|
|
dst[4] = 0xFF;
|
|
dst[6] = 0xFF;
|
|
}
|
|
if(c1){
|
|
dst[1] = c1[j*4+0];
|
|
dst[3] = c1[j*4+1];
|
|
dst[6] = c1[j*4+2];
|
|
dst[7] = c1[j*4+3];
|
|
}else{
|
|
dst[1] = 0xFF;
|
|
dst[3] = 0xFF;
|
|
dst[6] = 0xFF;
|
|
dst[7] = 0xFF;
|
|
}
|
|
dst += 8;
|
|
}
|
|
}
|
|
|
|
static void
|
|
instanceSANormals(Geometry *g, Mesh *m, int8 *dst)
|
|
{
|
|
float32 *norms = g->morphTargets[0].normals;
|
|
uint16 j;
|
|
for(uint32 i = 0; i < m->numIndices; i++){
|
|
j = m->indices[i];
|
|
if(norms){
|
|
dst[0] = norms[j*3+0]*127.0f;
|
|
dst[1] = norms[j*3+1]*127.0f;
|
|
dst[2] = norms[j*3+2]*127.0f;
|
|
dst[3] = 0;
|
|
}else
|
|
memset(dst, 0, 4);
|
|
dst += 4;
|
|
}
|
|
}
|
|
|
|
static void
|
|
saInstanceCB(MatPipeline *pipe, Geometry *g, Mesh *m, uint8 **data)
|
|
{
|
|
uint32 id = pipe->pluginData;
|
|
float vertScale = 128.0f;
|
|
if(id == 0x53f20085 || id == 0x53f20087 ||
|
|
id == 0x53f20089 || id == 0x53f2008b)
|
|
vertScale = 1024.0f;
|
|
ADCData *adc = PLUGINOFFSET(ADCData, g, adcOffset);
|
|
|
|
for(uint32 i = 0; i < nelem(pipe->attribs); i++){
|
|
rw::PipeAttribute *a = pipe->attribs[i];
|
|
if(a == &saXYZADC)
|
|
instanceSAPositions(g, m, adc->adcFormatted ? adc->adcBits : NULL,
|
|
(int16*)data[i], vertScale);
|
|
if(a == &saUV)
|
|
instanceSATex(g, m, (int16*)data[i]);
|
|
if(a == &saUV2)
|
|
instanceSADualTex(g, m, (int16*)data[i]);
|
|
if(a == &saRGBA)
|
|
instanceSAColors(g, m, (uint8*)data[i]);
|
|
if(a == &saRGBA2)
|
|
instanceSADualColors(g, m, (uint8*)data[i]);
|
|
if(a == &saNormal)
|
|
instanceSANormals(g, m, (int8*)data[i]);
|
|
if(a == &saWeights){
|
|
Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset);
|
|
instanceSkinData(g, m, skin, (uint32*)data[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
registerPDSPipes(void)
|
|
{
|
|
Pipeline *pipe;
|
|
MatPipeline *mpipe;
|
|
|
|
// Atomic pipes
|
|
|
|
pipe = new ps2::ObjPipeline(PLATFORM_PS2);
|
|
pipe->pluginID = ID_PDS;
|
|
pipe->pluginData = 0x53f20080;
|
|
ps2::registerPDSPipe(pipe);
|
|
|
|
pipe = new ps2::ObjPipeline(PLATFORM_PS2);
|
|
pipe->pluginID = ID_PDS;
|
|
pipe->pluginData = 0x53f20082;
|
|
ps2::registerPDSPipe(pipe);
|
|
|
|
pipe = new ps2::ObjPipeline(PLATFORM_PS2);
|
|
pipe->pluginID = ID_PDS;
|
|
pipe->pluginData = 0x53f20084;
|
|
ps2::registerPDSPipe(pipe);
|
|
|
|
pipe = new ps2::ObjPipeline(PLATFORM_PS2);
|
|
pipe->pluginID = ID_PDS;
|
|
pipe->pluginData = 0x53f20088;
|
|
ps2::registerPDSPipe(pipe);
|
|
|
|
// Material pipes
|
|
|
|
mpipe = new MatPipeline(PLATFORM_PS2);
|
|
mpipe->pluginID = ID_PDS;
|
|
mpipe->pluginData = 0x53f20081;
|
|
mpipe->attribs[0] = &saXYZADC;
|
|
mpipe->attribs[1] = &saUV;
|
|
mpipe->attribs[2] = &saRGBA;
|
|
uint32 vertCount = MatPipeline::getVertCount(VU_Lights, 3, 3, 2);
|
|
mpipe->setTriBufferSizes(3, vertCount);
|
|
mpipe->vifOffset = mpipe->inputStride*vertCount;
|
|
mpipe->instanceCB = saInstanceCB;
|
|
mpipe->preUninstCB = saPreCB;
|
|
mpipe->uninstanceCB = saUninstanceCB;
|
|
ps2::registerPDSPipe(mpipe);
|
|
|
|
mpipe = new MatPipeline(PLATFORM_PS2);
|
|
mpipe->pluginID = ID_PDS;
|
|
mpipe->pluginData = 0x53f20083;
|
|
mpipe->attribs[0] = &saXYZADC;
|
|
mpipe->attribs[1] = &saUV;
|
|
mpipe->attribs[2] = &saRGBA2;
|
|
vertCount = MatPipeline::getVertCount(VU_Lights, 3, 3, 2);
|
|
mpipe->setTriBufferSizes(3, vertCount);
|
|
mpipe->vifOffset = mpipe->inputStride*vertCount;
|
|
mpipe->instanceCB = saInstanceCB;
|
|
mpipe->preUninstCB = saPreCB;
|
|
mpipe->uninstanceCB = saUninstanceCB;
|
|
ps2::registerPDSPipe(mpipe);
|
|
|
|
mpipe = new MatPipeline(PLATFORM_PS2);
|
|
mpipe->pluginID = ID_PDS;
|
|
mpipe->pluginData = 0x53f20085;
|
|
mpipe->attribs[0] = &saXYZADC;
|
|
mpipe->attribs[1] = &saUV;
|
|
mpipe->attribs[3] = &saNormal;
|
|
vertCount = MatPipeline::getVertCount(VU_Lights, 4, 3, 2);
|
|
mpipe->setTriBufferSizes(4, vertCount);
|
|
mpipe->vifOffset = mpipe->inputStride*vertCount;
|
|
mpipe->instanceCB = saInstanceCB;
|
|
mpipe->preUninstCB = saPreCB;
|
|
mpipe->uninstanceCB = saUninstanceCB;
|
|
ps2::registerPDSPipe(mpipe);
|
|
|
|
mpipe = new MatPipeline(PLATFORM_PS2);
|
|
mpipe->pluginID = ID_PDS;
|
|
mpipe->pluginData = 0x53f20087;
|
|
mpipe->attribs[0] = &saXYZADC;
|
|
mpipe->attribs[1] = &saUV;
|
|
mpipe->attribs[3] = &saNormal;
|
|
vertCount = MatPipeline::getVertCount(0x3BD, 4, 3, 3);
|
|
mpipe->setTriBufferSizes(4, vertCount);
|
|
mpipe->vifOffset = mpipe->inputStride*vertCount;
|
|
mpipe->instanceCB = saInstanceCB;
|
|
mpipe->preUninstCB = saPreCB;
|
|
mpipe->uninstanceCB = saUninstanceCB;
|
|
ps2::registerPDSPipe(mpipe);
|
|
|
|
mpipe = new MatPipeline(PLATFORM_PS2);
|
|
mpipe->pluginID = ID_PDS;
|
|
mpipe->pluginData = 0x53f20089;
|
|
mpipe->attribs[0] = &saXYZADC;
|
|
mpipe->attribs[1] = &saUV;
|
|
mpipe->attribs[2] = &saNormal;
|
|
mpipe->attribs[3] = &saWeights;
|
|
// these values give vertCount = 0x33 :/
|
|
// vertCount = MatPipeline::getVertCount(0x2D0, 4, 3, 2);
|
|
vertCount = 0x30;
|
|
mpipe->setTriBufferSizes(4, vertCount);
|
|
mpipe->vifOffset = mpipe->inputStride*vertCount;
|
|
mpipe->instanceCB = saInstanceCB;
|
|
mpipe->preUninstCB = saPreCB;
|
|
mpipe->uninstanceCB = saUninstanceCB;
|
|
mpipe->postUninstCB = saPostCB;
|
|
ps2::registerPDSPipe(mpipe);
|
|
|
|
mpipe = new MatPipeline(PLATFORM_PS2);
|
|
mpipe->pluginID = ID_PDS;
|
|
mpipe->pluginData = 0x53f2008b;
|
|
mpipe->attribs[0] = &saXYZADC;
|
|
mpipe->attribs[1] = &saUV2;
|
|
mpipe->attribs[3] = &saNormal;
|
|
vertCount = MatPipeline::getVertCount(0x3BD, 4, 3, 3);
|
|
mpipe->setTriBufferSizes(4, vertCount);
|
|
mpipe->vifOffset = mpipe->inputStride*vertCount;
|
|
mpipe->instanceCB = saInstanceCB;
|
|
mpipe->preUninstCB = saPreCB;
|
|
mpipe->uninstanceCB = saUninstanceCB;
|
|
ps2::registerPDSPipe(mpipe);
|
|
|
|
mpipe = new MatPipeline(PLATFORM_PS2);
|
|
mpipe->pluginID = ID_PDS;
|
|
mpipe->pluginData = 0x53f2008d;
|
|
mpipe->attribs[0] = &saXYZADC;
|
|
mpipe->attribs[1] = &saUV;
|
|
mpipe->attribs[2] = &saRGBA;
|
|
mpipe->attribs[3] = &saNormal;
|
|
vertCount = MatPipeline::getVertCount(0x3BD, 4, 3, 3);
|
|
mpipe->setTriBufferSizes(4, vertCount);
|
|
mpipe->vifOffset = mpipe->inputStride*vertCount;
|
|
mpipe->instanceCB = saInstanceCB;
|
|
mpipe->preUninstCB = saPreCB;
|
|
mpipe->uninstanceCB = saUninstanceCB;
|
|
ps2::registerPDSPipe(mpipe);
|
|
|
|
mpipe = new MatPipeline(PLATFORM_PS2);
|
|
mpipe->pluginID = ID_PDS;
|
|
mpipe->pluginData = 0x53f2008f;
|
|
mpipe->attribs[0] = &saXYZADC;
|
|
mpipe->attribs[1] = &saUV;
|
|
mpipe->attribs[2] = &saRGBA2;
|
|
mpipe->attribs[3] = &saNormal;
|
|
vertCount = MatPipeline::getVertCount(0x3BD, 4, 3, 3);
|
|
mpipe->setTriBufferSizes(4, vertCount);
|
|
mpipe->vifOffset = mpipe->inputStride*vertCount;
|
|
mpipe->instanceCB = saInstanceCB;
|
|
mpipe->preUninstCB = saPreCB;
|
|
mpipe->uninstanceCB = saUninstanceCB;
|
|
ps2::registerPDSPipe(mpipe);
|
|
}
|
|
|
|
}
|