implemented PDS plugin and uninstancing in SA pipes

This commit is contained in:
aap 2015-12-16 20:25:22 +01:00
parent 305f93f738
commit 32dfcf0fd2
6 changed files with 574 additions and 112 deletions

View File

@ -289,33 +289,36 @@ Geometry::allocateData(void)
static int
isDegenerate(uint16 *idx)
{
// TODO: maybe check position instead of index?
return idx[0] == idx[1] ||
idx[0] == idx[2] ||
idx[1] == idx[2];
}
void
Geometry::generateTriangles(void)
Geometry::generateTriangles(int8 *adc)
{
MeshHeader *header = this->meshHeader;
assert(header != NULL);
this->numTriangles = 0;
Mesh *m = header->mesh;
int8 *adcbits = adc;
for(uint32 i = 0; i < header->numMeshes; i++){
if(m->numIndices < 3){
// shouldn't happen but it does
adcbits += m->numIndices;
m++;
continue;
}
if(header->flags == 1){ // tristrip
for(uint32 j = 0; j < m->numIndices-2; j++){
if(!isDegenerate(&m->indices[j]))
if(!(adc && adcbits[j+2]) &&
!isDegenerate(&m->indices[j]))
this->numTriangles++;
}
}else
this->numTriangles += m->numIndices/3;
adcbits += m->numIndices;
m++;
}
@ -324,8 +327,10 @@ Geometry::generateTriangles(void)
uint16 *f = this->triangles;
m = header->mesh;
adcbits = adc;
for(uint32 i = 0; i < header->numMeshes; i++){
if(m->numIndices < 3){
adcbits += m->numIndices;
m++;
continue;
}
@ -334,7 +339,8 @@ Geometry::generateTriangles(void)
this->numMaterials);
if(header->flags == 1) // tristrip
for(uint32 j = 0; j < m->numIndices-2; j++){
if(isDegenerate(&m->indices[j]))
if(adc && adcbits[j+2] ||
isDegenerate(&m->indices[j]))
continue;
*f++ = m->indices[j+1 + (j%2)];
*f++ = m->indices[j+0];
@ -348,6 +354,7 @@ Geometry::generateTriangles(void)
*f++ = matid;
*f++ = m->indices[j+2];
}
adcbits += m->numIndices;
m++;
}
}

View File

@ -21,7 +21,8 @@ namespace gta {
void
attachPlugins(void)
{
rw::ps2::registerPDSPlugin();
rw::ps2::registerPDSPlugin(12);
gta::registerPDSPipes();
rw::ps2::registerNativeRaster();
rw::xbox::registerNativeRaster();
@ -36,12 +37,12 @@ attachPlugins(void)
rw::registerHAnimPlugin();
gta::registerNodeNamePlugin();
rw::registerMatFXPlugin();
// rw::registerUVAnimPlugin();
rw::registerUVAnimPlugin();
rw::ps2::registerADCPlugin();
gta::registerExtraNormalsPlugin();
gta::registerExtraVertColorPlugin();
gta::registerEnvSpecPlugin();
// gta::registerBreakableModelPlugin();
gta::registerBreakableModelPlugin();
gta::registerCollisionPlugin();
gta::register2dEffectPlugin();
gta::registerPipelinePlugin();
@ -300,6 +301,16 @@ registerExtraNormalsPlugin(void)
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)
{
@ -759,4 +770,418 @@ registerCollisionPlugin(void)
writeCollision, getSizeCollision);
}
/*
* PS2
*/
using namespace ps2;
PipeAttribute saXYZADC = {
"saXYZADC",
AT_V4_16 | AT_RW
};
PipeAttribute saUV = {
"saUV",
AT_V2_16 | AT_RW
};
PipeAttribute saUV2 = {
"saUV2",
AT_V4_16 | AT_RW
};
PipeAttribute saRGBA = {
"saRGBA",
AT_V4_8 | AT_UNSGN | AT_RW
};
PipeAttribute saRGBA2 = {
"saRGBA2",
AT_V4_16 | AT_UNSGN | AT_RW
};
PipeAttribute saNormal = {
"saNormal",
AT_V4_8 | AT_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 {
float32 p[3];
float32 n[3];
float32 t0[2];
float32 t1[2];
uint8 c0[4];
uint8 c1[4];
float32 w[4];
uint8 i[4];
};
static void
saPreCB(MatPipeline *p, Geometry *geo)
{
// allocate ADC, extra colors, skin
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->c0[0] && cols0[1] == v->c0[1] &&
cols0[2] == v->c0[2] && cols0[3] == v->c0[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->t0[0] && tex0[1] == v->t0[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->p, v->t0, v->t1, v->c0, v->n);
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.c0[0] = colors[0];
v.c0[1] = colors[2];
v.c0[2] = colors[4];
v.c0[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.c0[0] = colors[0];
v.c0[1] = colors[1];
v.c0[2] = colors[2];
v.c0[3] = colors[3];
}
if(mask & 0x1000){
v.t0[0] = texcoords[0]/4096.0f;
v.t0[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
saInstanceCB(MatPipeline *, Geometry *g, Mesh *m, uint8 **data, int32 n)
{
}
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);
}
}

View File

@ -116,4 +116,8 @@ extern int32 collisionOffset;
void registerCollisionPlugin(void);
// PDS pipes
void registerPDSPipes(void);
}

View File

@ -58,6 +58,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32)
assert(a % 0x10 == 0);
#endif
stream->read(instance->data, instance->dataSize);
instance->material = geometry->meshHeader->mesh[i].material;
// sizedebug(instance);
}
}
@ -189,28 +190,6 @@ unfixDmaOffsets(InstanceData *inst)
// Pipeline
enum PS2Attribs {
AT_V2_32 = 0x64000000,
AT_V2_16 = 0x65000000,
AT_V2_8 = 0x66000000,
AT_V3_32 = 0x68000000,
AT_V3_16 = 0x69000000,
AT_V3_8 = 0x6A000000,
AT_V4_32 = 0x6C000000,
AT_V4_16 = 0x6D000000,
AT_V4_8 = 0x6E000000,
AT_UNSGN = 0x00004000,
AT_RW = 0x6
};
enum PS2AttibTypes {
AT_XYZ = 0,
AT_UV = 1,
AT_RGBA = 2,
AT_NORMAL = 3
};
PipeAttribute attribXYZ = {
"XYZ",
AT_V3_32
@ -254,10 +233,10 @@ static uint32
getBatchSize(MatPipeline *pipe, uint32 vertCount)
{
PipeAttribute *a;
uint32 size = 1;
uint32 size = 1; // ITOP &c. at the end
for(uint i = 0; i < nelem(pipe->attribs); i++)
if((a = pipe->attribs[i]) && (a->attrib & AT_RW) == 0){
size++;
size++; // UNPACK &c.
size += QWC(vertCount*attribSize(a->attrib));
}
return size;
@ -345,7 +324,7 @@ instanceNormal(uint32 *wp, Geometry *g, Mesh *m, uint32 idx, uint32 n)
MatPipeline::MatPipeline(uint32 platform)
: rw::Pipeline(platform), instanceCB(NULL), uninstanceCB(NULL),
allocateCB(NULL), finishCB(NULL)
preUninstCB(NULL), postUninstCB(NULL)
{
for(int i = 0; i < 10; i++)
this->attribs[i] = NULL;
@ -436,7 +415,7 @@ getInstMeshInfo(MatPipeline *pipe, Geometry *g, Mesh *m)
if(im.numBrokenAttribs == 0)
im.size = 1 + im.batchSize*(im.numBatches-1) + im.lastBatchSize;
else
im.size = 2*im.numBatches +
im.size = 2*im.numBrokenAttribs*im.numBatches +
(1+im.batchSize)*(im.numBatches-1) + 1+im.lastBatchSize;
/* figure out size and addresses of broken out sections */
@ -492,8 +471,11 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m)
*p++ = im.attribPos[i];
*p++ = 0x01000100 |
this->inputStride; // STCYCL
// Round up nverts so UNPACK will fit exactly into the DMA packet
// (can't pad with zeroes in broken out sections).
// TODO: check for clash with vifOffset somewhere
*p++ = (a->attrib&0xFF004000)
| 0x8000 | nverts << 16 | i; // UNPACK
| 0x8000 | (QWC(nverts*atsz)<<4)/atsz << 16 | i; // UNPACK
*p++ = 0x10000000;
*p++ = 0x0;
@ -572,10 +554,7 @@ MatPipeline::collectData(Geometry *g, InstanceData *inst, Mesh *m, uint8 *data[]
}
uint8 *datap[nelem(this->attribs)];
for(uint i = 0; i < nelem(this->attribs); i++){
datap[i] = data[i];
//printf("%p %x, %x\n", datap[i], datap[i]-datap[0], im.attribPos[i]*0x10);
}
memcpy(datap, data, sizeof(datap));
uint32 overlap = g->meshHeader->flags == 1 ? 2 : 0;
uint32 *p = (uint32*)inst->data;
@ -630,6 +609,7 @@ ObjPipeline::instance(Atomic *atomic)
if(m == NULL)
m = defaultMatPipe;
m->instance(geo, instance, mesh);
instance->material = mesh->material;
}
geo->geoflags |= Geometry::NATIVE;
}
@ -638,6 +618,9 @@ void
printVertCounts(InstanceData *inst, int flag)
{
uint32 *d = (uint32*)inst->data;
uint32 id = 0;
if(inst->material->pipeline)
id = inst->material->pipeline->pluginData;
int stride;
if(inst->arePointersFixed){
d += 4;
@ -646,15 +629,16 @@ printVertCounts(InstanceData *inst, int flag)
d += 4 + 4*QWC(attribSize(d[3])*((d[3]>>16)&0xFF));
}
if(d[2] == 0)
printf("ITOP %x %d (%d)\n", *d, stride, flag);
printf("ITOP %x %d (%d) %x\n", *d, stride, flag, id);
}else{
while((*d&0x70000000) == 0x30000000){
stride = d[2]&0xFF;
printf("UNPACK %x %d (%d) %x\n", d[3], stride, flag, id);
d += 8;
}
if((*d&0x70000000) == 0x10000000){
d += (*d&0xFFFF)*4;
printf("ITOP %x %d (%d)\n", *d, stride, flag);
printf("ITOP %x %d (%d) %x\n", *d, stride, flag, id);
}
}
}
@ -667,6 +651,7 @@ ObjPipeline::uninstance(Atomic *atomic)
return;
assert(geo->instData != NULL);
assert(geo->instData->platform == PLATFORM_PS2);
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
// highest possible number of vertices
geo->numVertices = geo->meshHeader->totalIndices;
geo->geoflags &= ~Geometry::NATIVE;
@ -675,18 +660,24 @@ ObjPipeline::uninstance(Atomic *atomic)
uint32 *flags = new uint32[geo->numVertices];
memset(flags, 0, 4*geo->numVertices);
memset(geo->meshHeader->mesh[0].indices, 0, 2*geo->meshHeader->totalIndices);
geo->numVertices = 0;
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
for(uint32 i = 0; i < header->numMeshes; i++){
Mesh *mesh = &geo->meshHeader->mesh[i];
InstanceData *instance = &header->instanceMeshes[i];
MatPipeline *m;
m = this->groupPipeline ?
this->groupPipeline :
(MatPipeline*)mesh->material->pipeline;
if(m == NULL) m = defaultMatPipe;
if(m->allocateCB) m->allocateCB(m, geo);
if(m->preUninstCB) m->preUninstCB(m, geo);
}
geo->numVertices = 0;
for(uint32 i = 0; i < header->numMeshes; i++){
Mesh *mesh = &geo->meshHeader->mesh[i];
InstanceData *instance = &header->instanceMeshes[i];
MatPipeline *m;
m = this->groupPipeline ?
this->groupPipeline :
(MatPipeline*)mesh->material->pipeline;
if(m == NULL) m = defaultMatPipe;
uint8 *data[nelem(m->attribs)] = { NULL };
uint8 *raw = m->collectData(geo, instance, mesh, data);
@ -701,21 +692,28 @@ ObjPipeline::uninstance(Atomic *atomic)
this->groupPipeline :
(MatPipeline*)mesh->material->pipeline;
if(m == NULL) m = defaultMatPipe;
if(m->finishCB) m->finishCB(m, geo);
if(m->postUninstCB) m->postUninstCB(m, geo);
}
geo->generateTriangles();
int8 *bits = NULL;
if(adcOffset){
ADCData *adc = PLUGINOFFSET(ADCData, geo, adcOffset);
if(adc->adcFormatted)
bits = adc->adcBits;
}
geo->generateTriangles(bits);
delete[] flags;
destroyNativeData(geo, 0, 0);
geo->instData = NULL;
/* for(uint32 i = 0; i < header->numMeshes; i++){
Mesh *mesh = &geometry->meshHeader->mesh[i];
/*
for(uint32 i = 0; i < header->numMeshes; i++){
Mesh *mesh = &geo->meshHeader->mesh[i];
InstanceData *instance = &header->instanceMeshes[i];
// printf("numIndices: %d\n", mesh->numIndices);
// printDMA(instance);
printVertCounts(instance, geometry->meshHeader->flags);
}*/
printVertCounts(instance, geo->meshHeader->flags);
}
*/
}
int32
@ -832,8 +830,6 @@ makeDefaultPipeline(void)
static void skinInstanceCB(MatPipeline*, Geometry*, Mesh*, uint8**, int32);
static void skinUninstanceCB(MatPipeline*, Geometry*, uint32*, Mesh*, uint8**);
static void skinAllocateCB(MatPipeline*, Geometry*);
static void skinFinishCB(MatPipeline*, Geometry*);
ObjPipeline*
makeSkinPipeline(void)
@ -851,8 +847,8 @@ makeSkinPipeline(void)
pipe->vifOffset = pipe->inputStride*vertCount;
pipe->instanceCB = skinInstanceCB;
pipe->uninstanceCB = skinUninstanceCB;
pipe->allocateCB = skinAllocateCB;
pipe->finishCB = skinFinishCB;
pipe->preUninstCB = skinPreCB;
pipe->postUninstCB = skinPostCB;
ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2);
opipe->pluginID = ID_SKIN;
@ -1108,15 +1104,12 @@ skinUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, u
}
}
static void
skinAllocateCB(MatPipeline*, Geometry *geo)
void
skinPreCB(MatPipeline*, Geometry *geo)
{
Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset);
// If weight/index data is allocated don't do it again as this function
// can be called multiple times per geometry.
if(skin == NULL || skin->weights)
if(skin == NULL)
return;
uint8 *data = skin->data;
float *invMats = skin->inverseMatrices;
// meshHeader->totalIndices is highest possible number of vertices again
@ -1125,8 +1118,8 @@ skinAllocateCB(MatPipeline*, Geometry *geo)
delete[] data;
}
static void
skinFinishCB(MatPipeline*, Geometry *geo)
void
skinPostCB(MatPipeline*, Geometry *geo)
{
Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset);
skin->findNumWeights(geo->numVertices);
@ -1135,6 +1128,8 @@ skinFinishCB(MatPipeline*, Geometry *geo)
// ADC
int32 adcOffset;
// TODO: look at PC SA rccam.dff bloodrb.dff, Xbox csbigbear.dff
static void
@ -1217,6 +1212,17 @@ debugadc(Geometry *g, MeshHeader *mh, ADCData *adc)
return n;
}
void
allocateADC(Geometry *geo)
{
ADCData *adc = PLUGINOFFSET(ADCData, geo, adcOffset);
adc->adcFormatted = 1;
adc->numBits = geo->meshHeader->totalIndices;
int32 size = adc->numBits+3 & ~3;
adc->adcBits = new int8[size];
memset(adc->adcBits, 0, size);
}
static void*
createADC(void *object, int32 offset, int32)
{
@ -1311,7 +1317,7 @@ getSizeADC(void *object, int32 offset, int32)
void
registerADCPlugin(void)
{
Geometry::registerPlugin(sizeof(ADCData), ID_ADC,
adcOffset = Geometry::registerPlugin(sizeof(ADCData), ID_ADC,
createADC, destroyADC, copyADC);
Geometry::registerPluginStream(ID_ADC,
readADC,
@ -1322,29 +1328,50 @@ registerADCPlugin(void)
// PDS plugin
struct PdsGlobals
{
Pipeline **pipes;
int32 maxPipes;
int32 numPipes;
};
PdsGlobals pdsGlobals;
Pipeline*
getPDSPipe(uint32 data)
{
for(int32 i = 0; i < pdsGlobals.numPipes; i++)
if(pdsGlobals.pipes[i]->pluginData == data)
return pdsGlobals.pipes[i];
return NULL;
}
void
registerPDSPipe(Pipeline *pipe)
{
assert(pdsGlobals.numPipes < pdsGlobals.maxPipes);
pdsGlobals.pipes[pdsGlobals.numPipes++] = pipe;
}
static void
atomicPDSRights(void *object, int32, int32, uint32 data)
{
Atomic *a = (Atomic*)object;
// TODO: lookup pipeline by data
a->pipeline = new ObjPipeline(PLATFORM_PS2);
a->pipeline->pluginID = ID_PDS;
a->pipeline->pluginData = data;
a->pipeline = (ObjPipeline*)getPDSPipe(data);
}
static void
materialPDSRights(void *object, int32, int32, uint32 data)
{
Material *m = (Material*)object;
// TODO: lookup pipeline by data
m->pipeline = new Pipeline(PLATFORM_PS2);
m->pipeline->pluginID = ID_PDS;
m->pipeline->pluginData = data;
m->pipeline = (ObjPipeline*)getPDSPipe(data);
}
void
registerPDSPlugin(void)
registerPDSPlugin(int32 n)
{
pdsGlobals.maxPipes = n;
pdsGlobals.numPipes = 0;
pdsGlobals.pipes = new Pipeline*[n];
Atomic::registerPlugin(0, ID_PDS, NULL, NULL, NULL);
Atomic::setStreamRightsCallback(ID_PDS, atomicPDSRights);
@ -1381,36 +1408,6 @@ printDMA(InstanceData *inst)
}
}
/* Function to specifically walk geometry chains */
void
walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size))
{
if(inst->arePointersFixed == 2)
return;
uint32 *base = (uint32*)inst->data;
uint32 *tag = (uint32*)inst->data;
for(;;){
switch(tag[0]&0x70000000){
// DMAcnt
case 0x10000000:
f(tag+2, 2+(tag[0]&0xFFFF)*4);
tag += (1+(tag[0]&0xFFFF))*4;
break;
// DMAref
case 0x30000000:
f(base + tag[1]*4, (tag[0]&0xFFFF)*4);
tag += 4;
break;
// DMAret
case 0x60000000:
f(tag+2, 2+(tag[0]&0xFFFF)*4);
return;
}
}
}
void
sizedebug(InstanceData *inst)
{

View File

@ -333,7 +333,7 @@ struct Geometry : PluginBase<Geometry>, Object
uint32 streamGetSize(void);
void addMorphTargets(int32 n);
void allocateData(void);
void generateTriangles(void);
void generateTriangles(int8 *adc = NULL);
enum Flags
{

View File

@ -23,6 +23,28 @@ enum {
VU_Lights = 0x3d0
};
enum PS2Attribs {
AT_V2_32 = 0x64000000,
AT_V2_16 = 0x65000000,
AT_V2_8 = 0x66000000,
AT_V3_32 = 0x68000000,
AT_V3_16 = 0x69000000,
AT_V3_8 = 0x6A000000,
AT_V4_32 = 0x6C000000,
AT_V4_16 = 0x6D000000,
AT_V4_8 = 0x6E000000,
AT_UNSGN = 0x00004000,
AT_RW = 0x6
};
enum PS2AttibTypes {
AT_XYZ = 0,
AT_UV = 1,
AT_RGBA = 2,
AT_NORMAL = 3
};
void *destroyNativeData(void *object, int32, int32);
void readNativeData(Stream *stream, int32 len, void *object, int32, int32);
void writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
@ -30,7 +52,6 @@ int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
void printDMA(InstanceData *inst);
void walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size));
void sizedebug(InstanceData *inst);
// only RW_PS2
@ -47,8 +68,8 @@ public:
PipeAttribute *attribs[10];
void (*instanceCB)(MatPipeline*, Geometry*, Mesh*, uint8**, int32);
void (*uninstanceCB)(MatPipeline*, Geometry*, uint32*, Mesh*, uint8**);
void (*allocateCB)(MatPipeline*, Geometry*);
void (*finishCB)(MatPipeline*, Geometry*);
void (*preUninstCB)(MatPipeline*, Geometry*);
void (*postUninstCB)(MatPipeline*, Geometry*);
static uint32 getVertCount(uint32 top, uint32 inAttribs,
uint32 outAttribs, uint32 outBufs) {
@ -72,6 +93,8 @@ public:
virtual void uninstance(Atomic *atomic);
};
void insertVertex(Geometry *geo, int32 i, uint32 mask, float *v, float *t0, float *t1, uint8 *c, float *n);
extern ObjPipeline *defaultObjPipe;
extern MatPipeline *defaultMatPipe;
@ -86,6 +109,9 @@ void readNativeSkin(Stream *stream, int32, void *object, int32 offset);
void writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset);
int32 getSizeNativeSkin(void *object, int32 offset);
void skinPreCB(MatPipeline*, Geometry*);
void skinPostCB(MatPipeline*, Geometry*);
// ADC plugin
// Each element in adcBits corresponds to an index in Mesh->indices,
@ -101,9 +127,11 @@ struct ADCData
int8 *adcBits;
int32 numBits;
};
extern int32 adcOffset;
void registerADCPlugin(void);
void allocateADC(Geometry *geo);
// PDS plugin
// IDs used by SA
@ -117,8 +145,9 @@ void registerADCPlugin(void);
// 4640 53f20084 53f2008b // vehicles
// 418 53f20088 53f20089 // peds
void registerPDSPlugin(void);
Pipeline *getPDSPipe(uint32 data);
void registerPDSPipe(Pipeline *pipe);
void registerPDSPlugin(int32 n);
// Native Texture and Raster