changed project structure, made VS projects, added d3d9 support and viewer, worked on xbox instancing

This commit is contained in:
aap
2015-09-06 13:31:42 +02:00
parent fca3327ae2
commit f09a1ab99f
37 changed files with 4192 additions and 216 deletions

View File

@@ -11,6 +11,8 @@
#include "rwobjects.h"
#include "rwps2.h"
#include "rwogl.h"
#include "rwxbox.h"
#include "rwd3d9.h"
using namespace std;
@@ -534,6 +536,10 @@ Atomic::init(void)
ps2::makeDefaultPipeline();
defaultPipelines[platformIdx[PLATFORM_OGL]] =
gl::makeDefaultPipeline();
defaultPipelines[platformIdx[PLATFORM_XBOX]] =
xbox::makeDefaultPipeline();
defaultPipelines[platformIdx[PLATFORM_D3D9]] =
d3d9::makeDefaultPipeline();
}
// Atomic Rights plugin

558
src/d3d9.cpp Normal file
View File

@@ -0,0 +1,558 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#include "rwd3d9.h"
using namespace std;
namespace rw {
namespace d3d9 {
#ifdef RW_D3D9
IDirect3DDevice9 *device = NULL;
#else
enum {
D3DLOCK_NOSYSLOCK = 0, // ignored
D3DPOOL_MANAGED = 0, // ignored
D3DPT_TRIANGLELIST = 4,
D3DPT_TRIANGLESTRIP = 5,
D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.)
D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.)
D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.)
D3DDECLTYPE_FLOAT4 = 3, // 4D float
D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range
// Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte
D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.)
D3DDECLTYPE_SHORT4 = 7, // 4D signed short
D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0
D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1)
D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values
D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused.
D3DDECLMETHOD_DEFAULT = 0,
D3DDECLUSAGE_POSITION = 0,
D3DDECLUSAGE_BLENDWEIGHT, // 1
D3DDECLUSAGE_BLENDINDICES, // 2
D3DDECLUSAGE_NORMAL, // 3
D3DDECLUSAGE_PSIZE, // 4
D3DDECLUSAGE_TEXCOORD, // 5
D3DDECLUSAGE_TANGENT, // 6
D3DDECLUSAGE_BINORMAL, // 7
D3DDECLUSAGE_TESSFACTOR, // 8
D3DDECLUSAGE_POSITIONT, // 9
D3DDECLUSAGE_COLOR, // 10
D3DDECLUSAGE_FOG, // 11
D3DDECLUSAGE_DEPTH, // 12
D3DDECLUSAGE_SAMPLE, // 13
};
#define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0}
#define D3DCOLOR_ARGB(a,r,g,b) \
((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
#endif
int vertFormatMap[] = {
-1, VERT_FLOAT2, VERT_FLOAT3, -1, VERT_ARGB
};
uint16*
lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags)
{
#ifdef RW_D3D9
uint16 *indices;
IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
ibuf->Lock(offset, size, (void**)&indices, flags);
return indices;
#else
return (uint16*)indexBuffer;
#endif
}
void
unlockIndices(void *indexBuffer)
{
#ifdef RW_D3D9
IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
ibuf->Unlock();
#endif
}
uint8*
lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags)
{
#ifdef RW_D3D9
uint8 *verts;
IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
vertbuf->Lock(offset, size, (void**)&verts, flags);
return verts;
#else
return (uint8*)vertexBuffer;
#endif
}
void
unlockVertices(void *vertexBuffer)
{
#ifdef RW_D3D9
IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
vertbuf->Unlock();
#endif
}
void*
createVertexDeclaration(VertexElement *elements)
{
#ifdef RW_D3D9
IDirect3DVertexDeclaration9 *decl = 0;
device->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &decl);
return decl;
#else
int n = 0;
VertexElement *e = (VertexElement*)elements;
while(e[n++].stream != 0xFF)
;
e = new VertexElement[n];
memcpy(e, elements, n*sizeof(VertexElement));
return e;
#endif
}
uint32
getDeclaration(void *declaration, VertexElement *elements)
{
#ifdef RW_D3D9
IDirect3DVertexDeclaration9 *decl = (IDirect3DVertexDeclaration9*)declaration;
UINT numElt;
decl->GetDeclaration((D3DVERTEXELEMENT9*)elements, &numElt);
return numElt;
#else
int n = 0;
VertexElement *e = (VertexElement*)declaration;
while(e[n++].stream != 0xFF)
;
if(elements)
memcpy(elements, declaration, n*sizeof(VertexElement));
return n;
#endif
}
void*
createIndexBuffer(uint32 length)
{
#ifdef RW_D3D9
IDirect3DIndexBuffer9 *ibuf;
device->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0);
return ibuf;
#else
return new uint8[length];
#endif
}
void*
createVertexBuffer(uint32 length, int32 pool)
{
#ifdef RW_D3D9
IDirect3DVertexBuffer9 *vbuf;
device->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, 0, (D3DPOOL)pool, &vbuf, 0);
return vbuf;
#else
return new uint8[length];
#endif
}
void*
destroyNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData != NULL);
assert(geometry->instData->platform == PLATFORM_D3D9);
// TODO
InstanceDataHeader *header =
(InstanceDataHeader*)geometry->instData;
delete header;
return object;
}
void
readNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
uint32 vers;
assert(findChunk(stream, ID_STRUCT, NULL, &vers));
assert(stream->readU32() == PLATFORM_D3D9);
InstanceDataHeader *header = new InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_D3D9;
int32 size = stream->readI32();
uint8 *data = new uint8[size];
stream->read(data, size);
uint8 *p = data;
header->serialNumber = *(uint32*)p; p += 4;
header->numMeshes = *(uint32*)p; p += 4;
header->indexBuffer = NULL; p += 4;
header->primType = *(uint32*)p; p += 4;
p += 16*2; // skip vertex streams, they're repeated with the vertex buffers
header->useOffsets = *(bool32*)p; p += 4;
header->vertexDeclaration = NULL; p += 4;
header->totalNumIndex = *(uint32*)p; p += 4;
header->totalNumVertex = *(uint32*)p; p += 4;
header->inst = new InstanceData[header->numMeshes];
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
inst->numIndex = *(uint32*)p; p += 4;
inst->minVert = *(uint32*)p; p += 4;
uint32 matid = *(uint32*)p; p += 4;
inst->material = geometry->materialList[matid];
inst->vertexAlpha = *(bool32*)p; p += 4;
inst->vertexShader = NULL; p += 4;
inst->baseIndex = 0; p += 4;
inst->numVertices = *(uint32*)p; p += 4;
inst->startIndex = *(uint32*)p; p += 4;
inst->numPrimitives = *(uint32*)p; p += 4;
inst++;
}
VertexElement elements[10];
uint32 numDeclarations = stream->readU32();
stream->read(elements, numDeclarations*8);
header->vertexDeclaration = createVertexDeclaration(elements);
header->indexBuffer = createIndexBuffer(header->totalNumIndex*sizeof(uint16));
uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
stream->read(indices, 2*header->totalNumIndex);
unlockIndices(header->indexBuffer);
VertexStream *s;
p = data;
for(int i = 0; i < 2; i++){
stream->read(p, 16);
s = &header->vertexStream[i];
s->vertexBuffer = (void*)*(uint32*)p; p += 4;
s->offset = 0; p += 4;
s->stride = *(uint32*)p; p += 4;
s->geometryFlags = *(uint16*)p; p += 2;
s->managed = *p++;
s->dynamicLock = *p++;
if(s->vertexBuffer == NULL)
continue;
// TODO: unset managed flag when using morph targets.
// also uses different buffer type and locks differently
s->vertexBuffer = createVertexBuffer(s->stride*header->totalNumVertex, D3DPOOL_MANAGED);
uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
stream->read(verts, s->stride*header->totalNumVertex);
unlockVertices(s->vertexBuffer);
}
// TODO: somehow depends on number of streams used (baseIndex = minVert when more than one)
inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
inst->baseIndex = inst->minVert + header->vertexStream[0].offset / header->vertexStream[0].stride;
inst++;
}
delete[] data;
}
void
writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
writeChunkHeader(stream, ID_STRUCT, len-12);
assert(geometry->instData != NULL);
assert(geometry->instData->platform == PLATFORM_D3D9);
stream->writeU32(PLATFORM_D3D9);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
int32 size = 64 + geometry->meshHeader->numMeshes*36;
uint8 *data = new uint8[size];
stream->writeI32(size);
uint8 *p = data;
*(uint32*)p = header->serialNumber; p += 4;
*(uint32*)p = header->numMeshes; p += 4;
p += 4; // skip index buffer
*(uint32*)p = header->primType; p += 4;
p += 16*2; // skip vertex streams, they're repeated with the vertex buffers
*(bool32*)p = header->useOffsets; p += 4;
p += 4; // skip vertex declaration
*(uint32*)p = header->totalNumIndex; p += 4;
*(uint32*)p = header->totalNumVertex; p += 4;
InstanceData *inst = header->inst;
for(uint32 i = 0; i < header->numMeshes; i++){
*(uint32*)p = inst->numIndex; p += 4;
*(uint32*)p = inst->minVert; p += 4;
int32 matid = findPointer(inst->material, (void**)geometry->materialList, geometry->numMaterials);
*(int32*)p = matid; p += 4;
*(bool32*)p = inst->vertexAlpha; p += 4;
*(uint32*)p = 0; p += 4; // vertex shader
*(uint32*)p = inst->baseIndex; p += 4; // not used but meh...
*(uint32*)p = inst->numVertices; p += 4;
*(uint32*)p = inst->startIndex; p += 4;
*(uint32*)p = inst->numPrimitives; p += 4;
inst++;
}
stream->write(data, size);
VertexElement elements[10];
uint32 numElt = getDeclaration(header->vertexDeclaration, elements);
stream->writeU32(numElt);
stream->write(elements, 8*numElt);
uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
stream->write(indices, 2*header->totalNumIndex);
unlockIndices(header->indexBuffer);
VertexStream *s;
for(int i = 0; i < 2; i++){
s = &header->vertexStream[i];
p = data;
*(uint32*)p = s->vertexBuffer ? 0xbadeaffe : 0; p += 4;
*(uint32*)p = s->offset; p += 4;
*(uint32*)p = s->stride; p += 4;
*(uint16*)p = s->geometryFlags; p += 2;
*p++ = s->managed;
*p++ = s->dynamicLock;
stream->write(data, 16);
if(s->vertexBuffer == NULL)
continue;
uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
stream->write(verts, s->stride*header->totalNumVertex);
unlockVertices(s->vertexBuffer);
}
delete[] data;
}
int32
getSizeNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData != NULL);
assert(geometry->instData->platform == PLATFORM_D3D9);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
int32 size = 12 + 4 + 4 + 64 + header->numMeshes*36;
uint32 numElt = getDeclaration(header->vertexDeclaration, NULL);
size += 4 + numElt*8;
size += 2*header->totalNumIndex;
size += 0x10 + header->vertexStream[0].stride*header->totalNumVertex;
size += 0x10 + header->vertexStream[1].stride*header->totalNumVertex;
return size;
}
void
registerNativeDataPlugin(void)
{
Geometry::registerPlugin(0, ID_NATIVEDATA,
NULL, destroyNativeData, NULL);
Geometry::registerPluginStream(ID_NATIVEDATA,
readNativeData,
writeNativeData,
getSizeNativeData);
}
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform),
instanceCB(NULL), uninstanceCB(NULL) { }
void
ObjPipeline::instance(Atomic *atomic)
{
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
header->platform = PLATFORM_D3D9;
header->serialNumber = 0;
header->numMeshes = meshh->numMeshes;
header->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
header->useOffsets = 0;
header->totalNumVertex = geo->numVertices;
header->totalNumIndex = meshh->totalIndices;
header->inst = new InstanceData[header->numMeshes];
header->indexBuffer = createIndexBuffer(header->totalNumIndex*sizeof(uint16));
uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
InstanceData *inst = header->inst;
Mesh *mesh = meshh->mesh;
uint32 startindex = 0;
for(uint32 i = 0; i < header->numMeshes; i++){
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
&inst->minVert, &inst->numVertices);
inst->numIndex = mesh->numIndices;
inst->material = mesh->material;
inst->vertexAlpha = 0;
inst->vertexShader = NULL;
inst->baseIndex = inst->minVert;
inst->startIndex = startindex;
inst->numPrimitives = header->primType == D3DPT_TRIANGLESTRIP ? inst->numIndex-2 : inst->numIndex/3;
if(inst->minVert == 0)
memcpy(&indices[inst->startIndex], mesh->indices, inst->numIndex*sizeof(uint16));
else
for(uint32 j = 0; j < inst->numIndex; j++)
indices[inst->startIndex+j] = mesh->indices[j]-inst->minVert;
startindex += inst->numIndex;
mesh++;
inst++;
}
unlockIndices(header->indexBuffer);
VertexStream *s;
for(int i = 0; i < 2; i++){
s = &header->vertexStream[i];
s->vertexBuffer = NULL;
s->offset = 0;
s->stride = 0;
s->geometryFlags = 0;
s->managed = 0;
s->dynamicLock = 0;
}
this->instanceCB(geo, header);
}
void
ObjPipeline::uninstance(Atomic *atomic)
{
assert(0 && "can't uninstance");
}
void
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
{
VertexElement dcl[6];
VertexStream *s = &header->vertexStream[0];
s->offset = 0;
s->managed = 1;
s->geometryFlags = 0;
s->dynamicLock = 0;
int i = 0;
dcl[i++] = {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0};
uint32 stride = 12;
s->geometryFlags |= 0x2;
bool isPrelit = (geo->geoflags & Geometry::PRELIT) != 0;
if(isPrelit){
dcl[i++] = {0, stride, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0};
s->geometryFlags |= 0x8;
stride += 4;
}
bool isTextured = (geo->geoflags & (Geometry::TEXTURED | Geometry::TEXTURED2)) != 0;
if(isTextured){
dcl[i++] = {0, stride, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0};
s->geometryFlags |= 0x10;
stride += 8;
}
bool hasNormals = (geo->geoflags & Geometry::NORMALS) != 0;
if(hasNormals){
dcl[i++] = {0, stride, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0};
s->geometryFlags |= 0x4;
stride += 12;
}
dcl[i] = D3DDECL_END();
header->vertexStream[0].stride = stride;
header->vertexDeclaration = createVertexDeclaration((VertexElement*)dcl);
s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, D3DPOOL_MANAGED);
uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++)
;
instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
geo->morphTargets[0].vertices,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
if(isPrelit){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
;
instColor(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
geo->colors,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
if(isTextured){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != 0; i++)
;
instV2d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
geo->texCoords[0],
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
if(hasNormals){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
;
instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
geo->morphTargets[0].normals,
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
}
unlockVertices(s->vertexBuffer);
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
pipe->instanceCB = defaultInstanceCB;
return pipe;
}
ObjPipeline*
makeSkinPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
pipe->instanceCB = defaultInstanceCB;
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
return pipe;
}
ObjPipeline*
makeMatFXPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
pipe->instanceCB = defaultInstanceCB;
pipe->pluginID = ID_MATFX;
pipe->pluginData = 0;
return pipe;
}
}
}

View File

@@ -223,7 +223,7 @@ Image::setSearchPath(const char *path)
::free(searchPaths);
numSearchPaths = 0;
if(path)
searchPaths = p = strdup(path);
searchPaths = p = _strdup(path);
else{
searchPaths = NULL;
return;
@@ -258,7 +258,7 @@ Image::getFilename(const char *name)
if(f){
fclose(f);
printf("found %s\n", name);
return strdup(name);
return _strdup(name);
}
return NULL;
}else

View File

@@ -54,74 +54,51 @@ printAttribInfo(AttribDesc *attribs, int n)
}
*/
void*
destroyNativeData(void *object, int32, int32)
#ifdef RW_OPENGL
void
uploadGeo(Geometry *geo)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
InstanceDataHeader *header =
(InstanceDataHeader*)geometry->instData;
delete[] header->attribs;
delete[] header->data;
delete header;
return object;
InstanceDataHeader *inst = (InstanceDataHeader*)geo->instData;
MeshHeader *meshHeader = geo->meshHeader;
glGenBuffers(1, &inst->vbo);
glBindBuffer(GL_ARRAY_BUFFER, inst->vbo);
glBufferData(GL_ARRAY_BUFFER, inst->dataSize,
inst->data, GL_STATIC_DRAW);
glGenBuffers(1, &inst->ibo);
glBindBuffer(GL_ARRAY_BUFFER, inst->ibo);
glBufferData(GL_ARRAY_BUFFER, meshHeader->totalIndices*2,
0, GL_STATIC_DRAW);
GLintptr offset = 0;
for(uint32 i = 0; i < meshHeader->numMeshes; i++){
Mesh *mesh = &meshHeader->mesh[i];
glBufferSubData(GL_ARRAY_BUFFER, offset, mesh->numIndices*2,
mesh->indices);
offset += mesh->numIndices*2;
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void
readNativeData(Stream *stream, int32, void *object, int32, int32)
setAttribPointers(InstanceDataHeader *inst)
{
Geometry *geometry = (Geometry*)object;
InstanceDataHeader *header = new InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_OGL;
header->vbo = 0;
header->ibo = 0;
header->numAttribs = stream->readU32();
header->attribs = new AttribDesc[header->numAttribs];
stream->read(header->attribs,
header->numAttribs*sizeof(AttribDesc));
header->dataSize = header->attribs[0].stride*geometry->numVertices;
header->data = new uint8[header->dataSize];
stream->read(header->data, header->dataSize);
static GLenum attribType[] = {
GL_FLOAT,
GL_BYTE, GL_UNSIGNED_BYTE,
GL_SHORT, GL_UNSIGNED_SHORT
};
for(int32 i = 0; i < inst->numAttribs; i++){
AttribDesc *a = &inst->attribs[i];
glEnableVertexAttribArray(a->index);
glVertexAttribPointer(a->index, a->size, attribType[a->type],
a->normalized, a->stride,
(void*)(uint64)a->offset);
}
}
#endif
void
printPipeinfo(Atomic *a)
{
Geometry *g = a->geometry;
if(g->instData == NULL || g->instData->platform != PLATFORM_OGL)
return;
int32 plgid = 0;
if(a->pipeline)
plgid = a->pipeline->pluginID;
printf("%s %x: ", debugFile, plgid);
InstanceDataHeader *h = (InstanceDataHeader*)g->instData;
for(int i = 0; i < h->numAttribs; i++)
printf("%x(%x) ", h->attribs[i].index, h->attribs[i].type);
printf("\n");
}
void
writeNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
stream->writeU32(header->numAttribs);
stream->write(header->attribs, header->numAttribs*sizeof(AttribDesc));
stream->write(header->data, header->dataSize);
}
int32
getSizeNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
return 4 + header->numAttribs*sizeof(AttribDesc) + header->dataSize;
}
static void
packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale=1.0f)
{
int8 *i8dst;
@@ -175,6 +152,138 @@ packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale=1.0f)
}
}
void
unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale=1.0f)
{
int8 *i8src;
uint16 *u16src;
int16 *i16src;
switch(a->type){
case 0: // float
memcpy(dst, src, a->size*4);
break;
// TODO: maybe have loop inside if?
case 1: // byte
i8src = (int8*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = i8src[i]/scale;
else
dst[i] = i8src[i]/127.0f;
}
break;
case 2: // ubyte
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = src[i]/scale;
else
dst[i] = src[i]/255.0f;
}
break;
case 3: // short
i16src = (int16*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = i16src[i]/scale;
else
dst[i] = i16src[i]/32767.0f;
}
break;
case 4: // ushort
u16src = (uint16*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = u16src[i]/scale;
else
dst[i] = u16src[i]/65435.0f;
}
break;
}
}
void*
destroyNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
InstanceDataHeader *header =
(InstanceDataHeader*)geometry->instData;
delete[] header->attribs;
delete[] header->data;
delete header;
return object;
}
void
readNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
InstanceDataHeader *header = new InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_OGL;
header->vbo = 0;
header->ibo = 0;
header->numAttribs = stream->readU32();
header->attribs = new AttribDesc[header->numAttribs];
stream->read(header->attribs,
header->numAttribs*sizeof(AttribDesc));
header->dataSize = header->attribs[0].stride*geometry->numVertices;
header->data = new uint8[header->dataSize];
stream->read(header->data, header->dataSize);
}
void
writeNativeData(Stream *stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
stream->writeU32(header->numAttribs);
stream->write(header->attribs, header->numAttribs*sizeof(AttribDesc));
stream->write(header->data, header->dataSize);
}
int32
getSizeNativeData(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
return 4 + header->numAttribs*sizeof(AttribDesc) + header->dataSize;
}
void
registerNativeDataPlugin(void)
{
Geometry::registerPlugin(0, ID_NATIVEDATA,
NULL, destroyNativeData, NULL);
Geometry::registerPluginStream(ID_NATIVEDATA,
readNativeData,
writeNativeData,
getSizeNativeData);
}
void
printPipeinfo(Atomic *a)
{
Geometry *g = a->geometry;
if(g->instData == NULL || g->instData->platform != PLATFORM_OGL)
return;
int32 plgid = 0;
if(a->pipeline)
plgid = a->pipeline->pluginID;
printf("%s %x: ", debugFile, plgid);
InstanceDataHeader *h = (InstanceDataHeader*)g->instData;
for(int i = 0; i < h->numAttribs; i++)
printf("%x(%x) ", h->attribs[i].index, h->attribs[i].type);
printf("\n");
}
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform), numCustomAttribs(0),
instanceCB(NULL), uninstanceCB(NULL) { }
@@ -305,60 +414,6 @@ ObjPipeline::instance(Atomic *atomic)
geo->geoflags |= Geometry::NATIVE;
}
static void
unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale=1.0f)
{
int8 *i8src;
uint16 *u16src;
int16 *i16src;
switch(a->type){
case 0: // float
memcpy(dst, src, a->size*4);
break;
// TODO: maybe have loop inside if?
case 1: // byte
i8src = (int8*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = i8src[i]/scale;
else
dst[i] = i8src[i]/127.0f;
}
break;
case 2: // ubyte
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = src[i]/scale;
else
dst[i] = src[i]/255.0f;
}
break;
case 3: // short
i16src = (int16*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = i16src[i]/scale;
else
dst[i] = i16src[i]/32767.0f;
}
break;
case 4: // ushort
u16src = (uint16*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = u16src[i]/scale;
else
dst[i] = u16src[i]/65435.0f;
}
break;
}
}
void
ObjPipeline::uninstance(Atomic *atomic)
{
@@ -438,70 +493,20 @@ makeDefaultPipeline(void)
return pipe;
}
#ifdef RW_OPENGL
void
uploadGeo(Geometry *geo)
{
InstanceDataHeader *inst = (InstanceDataHeader*)geo->instData;
MeshHeader *meshHeader = geo->meshHeader;
glGenBuffers(1, &inst->vbo);
glBindBuffer(GL_ARRAY_BUFFER, inst->vbo);
glBufferData(GL_ARRAY_BUFFER, inst->dataSize,
inst->data, GL_STATIC_DRAW);
glGenBuffers(1, &inst->ibo);
glBindBuffer(GL_ARRAY_BUFFER, inst->ibo);
glBufferData(GL_ARRAY_BUFFER, meshHeader->totalIndices*2,
0, GL_STATIC_DRAW);
GLintptr offset = 0;
for(uint32 i = 0; i < meshHeader->numMeshes; i++){
Mesh *mesh = &meshHeader->mesh[i];
glBufferSubData(GL_ARRAY_BUFFER, offset, mesh->numIndices*2,
mesh->indices);
offset += mesh->numIndices*2;
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void
setAttribPointers(InstanceDataHeader *inst)
{
static GLenum attribType[] = {
GL_FLOAT,
GL_BYTE, GL_UNSIGNED_BYTE,
GL_SHORT, GL_UNSIGNED_SHORT
};
for(int32 i = 0; i < inst->numAttribs; i++){
AttribDesc *a = &inst->attribs[i];
glEnableVertexAttribArray(a->index);
glVertexAttribPointer(a->index, a->size, attribType[a->type],
a->normalized, a->stride,
(void*)(uint64)a->offset);
}
}
#endif
// Skin
void
readNativeSkin(Stream *stream, int32, void *object, int32 offset)
{
uint8 header[4];
uint32 vers;
Geometry *geometry = (Geometry*)object;
assert(findChunk(stream, ID_STRUCT, NULL, &vers));
assert(stream->readU32() == PLATFORM_OGL);
stream->read(header, 4);
Skin *skin = new Skin;
*PLUGINOFFSET(Skin*, geometry, offset) = skin;
skin->numBones = header[0];
// should be 0
skin->numUsedBones = header[1];
skin->maxIndex = header[2];
assert(skin->numUsedBones == 0);
assert(skin->maxIndex == 0);
skin->numBones = stream->readI32();
skin->numUsedBones = 0;
skin->maxIndex = 0;
int32 size = skin->numBones*64 + 15;
uint8 *data = new uint8[size];

View File

@@ -54,4 +54,71 @@ ObjPipeline::render(Atomic*)
fprintf(stderr, "This pipeline can't render\n");
}
// helper functions
void
findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, uint32 *numVertices)
{
uint32 min = 0xFFFFFFFF;
uint32 max = 0;
while(numIndices--){
if(*indices < min)
min = *indices;
if(*indices > max)
max = *indices;
indices++;
}
*minVert = min;
*numVertices = max - min + 1;
}
void
instV3d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride)
{
if(type == VERT_FLOAT3)
for(uint32 i = 0; i < numVertices; i++){
memcpy(dst, src, 12);
dst += stride;
src += 3;
}
else if(type == VERT_COMPNORM)
for(uint32 i = 0; i < numVertices; i++){
uint32 n = ((((uint32)(src[2] * 511.0f)) & 0x3ff) << 22) |
((((uint32)(src[1] * 1023.0f)) & 0x7ff) << 11) |
((((uint32)(src[0] * 1023.0f)) & 0x7ff) << 0);
*(uint32*)dst = n;
dst += stride;
src += 3;
}
else
assert(0 && "unsupported instV3d type");
}
void
instV2d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride)
{
assert(type == VERT_FLOAT2);
for(uint32 i = 0; i < numVertices; i++){
memcpy(dst, src, 8);
dst += stride;
src += 2;
}
}
bool32
instColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride)
{
assert(type == VERT_ARGB);
bool32 hasAlpha = 0;
for(uint32 i = 0; i < numVertices; i++){
uint32 col = COLOR_ARGB(src[3], src[0], src[1], src[2]);
if(src[3] < 0xFF)
hasAlpha = 1;
memcpy(dst, &col, 4);
dst += stride;
src += 4;
}
return hasAlpha;
}
}

View File

@@ -11,6 +11,7 @@
#include "rwobjects.h"
#include "rwps2.h"
#include "rwxbox.h"
#include "rwd3d9.h"
#include "rwogl.h"
using namespace std;
@@ -261,6 +262,10 @@ destroyNativeData(void *object, int32 offset, int32 size)
return object;
if(geometry->instData->platform == PLATFORM_PS2)
return ps2::destroyNativeData(object, offset, size);
if(geometry->instData->platform == PLATFORM_XBOX)
return xbox::destroyNativeData(object, offset, size);
if(geometry->instData->platform == PLATFORM_D3D9)
return d3d9::destroyNativeData(object, offset, size);
if(geometry->instData->platform == PLATFORM_OGL)
return gl::destroyNativeData(object, offset, size);
return object;
@@ -278,13 +283,14 @@ readNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s)
readChunkHeaderInfo(stream, &header);
if(header.type == ID_STRUCT &&
libraryIDPack(header.version, header.build) == libid){
// must be PS2 or Xbox
platform = stream->readU32();
stream->seek(-16);
if(platform == PLATFORM_PS2)
ps2::readNativeData(stream, len, object, o, s);
else if(platform == PLATFORM_XBOX)
xbox::readNativeData(stream, len, object, o, s);
else if(platform == PLATFORM_D3D9)
d3d9::readNativeData(stream, len, object, o, s);
else{
fprintf(stderr, "unknown platform %d\n", platform);
stream->seek(len);
@@ -305,6 +311,8 @@ writeNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s)
ps2::writeNativeData(stream, len, object, o, s);
else if(geometry->instData->platform == PLATFORM_XBOX)
xbox::writeNativeData(stream, len, object, o, s);
else if(geometry->instData->platform == PLATFORM_D3D9)
d3d9::writeNativeData(stream, len, object, o, s);
else if(geometry->instData->platform == PLATFORM_OGL)
gl::writeNativeData(stream, len, object, o, s);
}
@@ -319,6 +327,8 @@ getSizeNativeData(void *object, int32 offset, int32 size)
return ps2::getSizeNativeData(object, offset, size);
else if(geometry->instData->platform == PLATFORM_XBOX)
return xbox::getSizeNativeData(object, offset, size);
else if(geometry->instData->platform == PLATFORM_D3D9)
return d3d9::getSizeNativeData(object, offset, size);
else if(geometry->instData->platform == PLATFORM_OGL)
return gl::getSizeNativeData(object, offset, size);
return -1;
@@ -408,10 +418,10 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32)
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];
// probably rw::version >= 0x34000
bool oldFormat = skin->numUsedBones == 0;
skin->allocateData(geometry->numVertices);
@@ -490,6 +500,8 @@ getSizeSkin(void *object, int32 offset, int32)
return xbox::getSizeNativeSkin(object, offset);
if(geometry->instData->platform == PLATFORM_OGL)
return gl::getSizeNativeSkin(object, offset);
if(geometry->instData->platform == PLATFORM_D3D9)
return -1;
assert(0 && "unsupported native skin platform");
}
@@ -525,6 +537,10 @@ registerSkinPlugin(void)
ps2::makeSkinPipeline();
skinGlobals.pipelines[platformIdx[PLATFORM_OGL]] =
gl::makeSkinPipeline();
skinGlobals.pipelines[platformIdx[PLATFORM_XBOX]] =
xbox::makeSkinPipeline();
skinGlobals.pipelines[platformIdx[PLATFORM_D3D9]] =
d3d9::makeSkinPipeline();
skinGlobals.offset = Geometry::registerPlugin(sizeof(Skin*), ID_SKIN,
createSkin,
@@ -909,6 +925,10 @@ registerMatFXPlugin(void)
ps2::makeMatFXPipeline();
matFXGlobals.pipelines[platformIdx[PLATFORM_OGL]] =
gl::makeMatFXPipeline();
matFXGlobals.pipelines[platformIdx[PLATFORM_XBOX]] =
xbox::makeMatFXPipeline();
matFXGlobals.pipelines[platformIdx[PLATFORM_D3D9]] =
d3d9::makeMatFXPipeline();
matFXGlobals.atomicOffset =
Atomic::registerPlugin(sizeof(int32), ID_MATFX,

View File

@@ -20,6 +20,8 @@ int build = 0xFFFF;
int platform = PLATFORM_PS2;
#elif RW_OPENGL
int platform = PLATFORM_OGL;
#elif RW_D3D9
int platform = PLATFORM_D3D9;
#else
int platform = PLATFORM_NULL;
#endif

95
src/rwd3d9.h Normal file
View File

@@ -0,0 +1,95 @@
#ifdef RW_D3D9
#include <d3d9.h>
#endif
namespace rw {
namespace d3d9 {
struct VertexElement
{
uint16 stream;
uint16 offset;
uint8 type;
uint8 method;
uint8 usage;
uint8 usageIndex;
};
struct VertexStream
{
void *vertexBuffer;
uint32 offset;
uint32 stride;
uint16 geometryFlags;
uint8 managed;
uint8 dynamicLock;
};
struct InstanceData
{
uint32 numIndex;
uint32 minVert;
Material *material;
bool32 vertexAlpha;
void *vertexShader;
uint32 baseIndex;
uint32 numVertices;
uint32 startIndex;
uint32 numPrimitives;
};
struct InstanceDataHeader : rw::InstanceDataHeader
{
uint32 serialNumber;
uint32 numMeshes;
void *indexBuffer;
uint32 primType;
VertexStream vertexStream[2];
bool32 useOffsets;
void *vertexDeclaration;
uint32 totalNumIndex;
uint32 totalNumVertex;
InstanceData *inst;
};
#ifdef RW_D3D9
extern IDirect3DDevice9 *device;
#endif
extern int vertFormatMap[];
uint16 *lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags);
void unlockIndices(void *indexBuffer);
uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags);
void unlockVertices(void *vertexBuffer);
void *createVertexDeclaration(VertexElement *elements);
uint32 getDeclaration(void *declaration, VertexElement *elements);
void *createIndexBuffer(uint32 length);
void *createVertexBuffer(uint32 length, int32 pool);
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);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
class ObjPipeline : public rw::ObjPipeline
{
public:
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
ObjPipeline(uint32 platform);
virtual void instance(Atomic *atomic);
virtual void uninstance(Atomic *atomic);
};
ObjPipeline *makeDefaultPipeline(void);
ObjPipeline *makeSkinPipeline(void);
ObjPipeline *makeMatFXPipeline(void);
}
}

View File

@@ -1,6 +1,8 @@
namespace rw {
namespace gl {
// NOTE: This is not really RW OpenGL! It's specific to WarDrum's GTA ports
struct AttribDesc
{
// arguments to glVertexAttribPointer (should use OpenGL types here)
@@ -26,12 +28,19 @@ struct InstanceDataHeader : rw::InstanceDataHeader
uint32 ibo;
};
// only RW_OPENGL
void uploadGeo(Geometry *geo);
void setAttribPointers(InstanceDataHeader *inst);
void packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale);
void unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale);
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);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
void instance(Atomic *atomic);
void printPipeinfo(Atomic *a);
class ObjPipeline : public rw::ObjPipeline
@@ -48,10 +57,6 @@ public:
ObjPipeline *makeDefaultPipeline(void);
// only RW_OPENGL
void uploadGeo(Geometry *geo);
void setAttribPointers(InstanceDataHeader *inst);
// Skin plugin
void readNativeSkin(Stream *stream, int32, void *object, int32 offset);

View File

@@ -30,4 +30,27 @@ public:
virtual void render(Atomic *atomic);
};
void findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, uint32 *numVertices);
// everything xbox, d3d8 and d3d9 may want to use
enum {
VERT_BYTE2 = 1,
VERT_BYTE3,
VERT_SHORT2,
VERT_SHORT3,
VERT_NORMSHORT2,
VERT_NORMSHORT3,
VERT_FLOAT2,
VERT_FLOAT3,
VERT_ARGB,
VERT_COMPNORM
};
#define COLOR_ARGB(a,r,g,b) \
((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
void instV3d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride);
void instV2d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride);
bool32 instColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride);
}

View File

@@ -13,9 +13,9 @@ typedef void (*RightsCallback)(void *object, int32 offset, int32 size, uint32 da
struct Plugin
{
int offset;
int size;
uint id;
int32 offset;
int32 size;
uint32 id;
Constructor constructor;
Destructor destructor;
CopyConstructor copy;
@@ -29,8 +29,8 @@ struct Plugin
template <typename T>
struct PluginBase
{
static int s_defaultSize;
static int s_size;
static int32 s_defaultSize;
static int32 s_size;
static Plugin *s_plugins;
void constructPlugins(void);
@@ -41,12 +41,12 @@ struct PluginBase
int streamGetPluginSize(void);
void assertRights(uint32 pluginID, uint32 data);
static int registerPlugin(int size, uint id,
static int registerPlugin(int32 size, uint32 id,
Constructor, Destructor, CopyConstructor);
static int registerPluginStream(uint id,
static int registerPluginStream(uint32 id,
StreamRead, StreamWrite, StreamGetSize);
static int setStreamRightsCallback(uint id, RightsCallback cb);
static int getPluginOffset(uint id);
static int setStreamRightsCallback(uint32 id, RightsCallback cb);
static int getPluginOffset(uint32 id);
static void *operator new(size_t size);
static void operator delete(void *p);
};
@@ -118,11 +118,11 @@ PluginBase<T>::streamWritePlugins(Stream *stream)
}
}
template <typename T> int
template <typename T> int32
PluginBase<T>::streamGetPluginSize(void)
{
int size = 0;
int plgsize;
int32 size = 0;
int32 plgsize;
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->getSize &&
(plgsize = p->getSize(this, p->offset, p->size)) >= 0)
@@ -142,8 +142,8 @@ PluginBase<T>::assertRights(uint32 pluginID, uint32 data)
}
}
template <typename T> int
PluginBase<T>::registerPlugin(int size, uint id,
template <typename T> int32
PluginBase<T>::registerPlugin(int32 size, uint32 id,
Constructor ctor, Destructor dtor, CopyConstructor cctor)
{
Plugin *p = new Plugin;
@@ -165,8 +165,8 @@ PluginBase<T>::registerPlugin(int size, uint id,
return p->offset;
}
template <typename T> int
PluginBase<T>::registerPluginStream(uint id,
template <typename T> int32
PluginBase<T>::registerPluginStream(uint32 id,
StreamRead read, StreamWrite write, StreamGetSize getSize)
{
for(Plugin *p = PluginBase<T>::s_plugins; p; p = p->next)
@@ -179,8 +179,8 @@ PluginBase<T>::registerPluginStream(uint id,
return -1;
}
template <typename T> int
PluginBase<T>::setStreamRightsCallback(uint id, RightsCallback cb)
template <typename T> int32
PluginBase<T>::setStreamRightsCallback(uint32 id, RightsCallback cb)
{
for(Plugin *p = PluginBase<T>::s_plugins; p; p = p->next)
if(p->id == id){
@@ -190,8 +190,8 @@ PluginBase<T>::setStreamRightsCallback(uint id, RightsCallback cb)
return -1;
}
template <typename T> int
PluginBase<T>::getPluginOffset(uint id)
template <typename T> int32
PluginBase<T>::getPluginOffset(uint32 id)
{
for(Plugin *p = PluginBase<T>::s_plugins; p; p = p->next)
if(p->id == id)

View File

@@ -33,14 +33,37 @@ void writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
class ObjPipeline : public rw::ObjPipeline
{
public:
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
ObjPipeline(uint32 platform);
virtual void instance(Atomic *atomic);
virtual void uninstance(Atomic *atomic);
};
ObjPipeline *makeDefaultPipeline(void);
// Skin plugin
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);
ObjPipeline *makeSkinPipeline(void);
ObjPipeline *makeMatFXPipeline(void);
// Vertex Format plugin
extern uint32 vertexFormatSizes[6];
uint32 *getVertexFmt(Geometry *g);
uint32 makeVertexFmt(int32 flags, uint32 numTexSets);
uint32 getVertexFmtStride(uint32 fmt);
void registerVertexFormatPlugin(void);
}

View File

@@ -16,6 +16,11 @@ using namespace std;
namespace rw {
namespace xbox {
enum {
D3DPT_TRIANGLELIST = 5,
D3DPT_TRIANGLESTRIP = 6,
};
void*
destroyNativeData(void *object, int32, int32)
{
@@ -24,6 +29,7 @@ destroyNativeData(void *object, int32, int32)
assert(geometry->instData->platform == PLATFORM_XBOX);
InstanceDataHeader *header =
(InstanceDataHeader*)geometry->instData;
// TODO
delete header;
return object;
}
@@ -84,12 +90,11 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
assert(geometry->instData != NULL);
assert(geometry->instData->platform == PLATFORM_XBOX);
stream->writeU32(PLATFORM_XBOX);
assert(rw::version >= 0x35000 && "can't write native Xbox data < 0x35000");
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
// we just fill header->data and write that
uint8 *p = header->data+0x18;
//uint8 *end = (uint8*)header->begin->indexBuffer;
//memset(p, 0xAB, end-p);
*(int32*)p = header->size; p += 4;
*(uint16*)p = header->serialNumber; p += 2;
*(uint16*)p = header->numMeshes; p += 2;
@@ -137,6 +142,124 @@ registerNativeDataPlugin(void)
getSizeNativeData);
}
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform),
instanceCB(NULL), uninstanceCB(NULL) { }
void
ObjPipeline::instance(Atomic *atomic)
{
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
header->platform = PLATFORM_XBOX;
header->size = 0x24 + meshh->numMeshes*0x18 + 0x10;
Mesh *mesh = meshh->mesh;
for(uint32 i = 0; i < meshh->numMeshes; i++)
header->size += (mesh++->numIndices*2 + 0xF) & ~0xF;
// The 0x18 byte are the resentryheader.
// We don't have it but it's used for alignment.
header->data = new uint8[header->size + 0x18];
header->serialNumber = 0;
header->numMeshes = meshh->numMeshes;
header->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
header->numVertices = geo->numVertices;
header->vertexAlpha = 0;
// set by the instanceCB
header->stride = 0;
header->vertexBuffer = NULL;
InstanceData *inst = new InstanceData[header->numMeshes];
header->begin = inst;
mesh = meshh->mesh;
uint8 *indexbuf = (uint8*)header->data + ((0x18 + 0x24 + header->numMeshes*0x18 + 0xF)&~0xF);
for(uint32 i = 0; i < header->numMeshes; i++){
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
&inst->minVert, (uint32*)&inst->numVertices);
inst->numIndices = mesh->numIndices;
inst->indexBuffer = indexbuf;
memcpy(inst->indexBuffer, mesh->indices, inst->numIndices*sizeof(uint16));
indexbuf += (inst->numIndices*2 + 0xF) & ~0xF;
inst->material = mesh->material;
inst->vertexShader = 0; // TODO?
mesh++;
inst++;
}
header->end = inst;
this->instanceCB(geo, header);
}
void
ObjPipeline::uninstance(Atomic *atomic)
{
assert(0 && "can't uninstance");
}
int v3dFormatMap[] = {
-1, VERT_BYTE3, VERT_SHORT3, VERT_NORMSHORT3, VERT_COMPNORM, VERT_FLOAT3
};
int v2dFormatMap[] = {
-1, VERT_BYTE2, VERT_SHORT2, VERT_NORMSHORT2, VERT_COMPNORM, VERT_FLOAT2
};
void
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
{
uint32 *vertexFmt = getVertexFmt(geo);
if(*vertexFmt == 0)
*vertexFmt = makeVertexFmt(geo->geoflags, geo->numTexCoordSets);
header->stride = getVertexFmtStride(*vertexFmt);
header->vertexBuffer = new uint8[header->stride*header->numVertices];
uint32 offset = 0;
uint8 *dst = (uint8*)header->vertexBuffer;
uint32 fmt = *vertexFmt;
uint32 sel = fmt & 0xF;
instV3d(v3dFormatMap[sel], dst, geo->morphTargets[0].vertices,
header->numVertices, header->stride);
dst += sel == 4 ? 4 : 3*vertexFormatSizes[sel];
sel = (fmt >> 4) & 0xF;
if(sel){
instV3d(v3dFormatMap[sel], dst, geo->morphTargets[0].normals,
header->numVertices, header->stride);
dst += sel == 4 ? 4 : 3*vertexFormatSizes[sel];
}
if(fmt & 0x1000000){
header->vertexAlpha = instColor(VERT_ARGB, dst, geo->colors,
header->numVertices, header->stride);
dst += 4;
}
for(int i = 0; i < 4; i++){
sel = (fmt >> (i*4 + 8)) & 0xF;
if(sel == 0)
break;
instV2d(v2dFormatMap[sel], dst, geo->texCoords[i],
header->numVertices, header->stride);
dst += sel == 4 ? 4 : 2*vertexFormatSizes[sel];
}
if(fmt & 0xE000000)
assert(0 && "can't instance tangents or whatever it is");
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX);
pipe->instanceCB = defaultInstanceCB;
return pipe;
}
// Skin plugin
struct NativeSkin
@@ -213,14 +336,87 @@ getSizeNativeSkin(void *object, int32 offset)
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
if(skin == NULL)
return -1;
assert(skin->platformData);
if(skin->platformData == NULL)
return -1;
NativeSkin *natskin = (NativeSkin*)skin->platformData;
return 12 + 8 + 2*256*4 + 4*4 +
natskin->stride*geometry->numVertices + skin->numBones*64 + 12;
}
void
skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
{
defaultInstanceCB(geo, header);
}
ObjPipeline*
makeSkinPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX);
pipe->instanceCB = skinInstanceCB;
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
return pipe;
}
ObjPipeline*
makeMatFXPipeline(void)
{
ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX);
pipe->instanceCB = defaultInstanceCB;
pipe->pluginID = ID_MATFX;
pipe->pluginData = 0;
return pipe;
}
// Vertex Format Plugin
static int32 vertexFmtOffset;
uint32 vertexFormatSizes[6] = {
0, 1, 2, 2, 4, 4
};
uint32*
getVertexFmt(Geometry *g)
{
return PLUGINOFFSET(uint32, g, vertexFmtOffset);
}
uint32
makeVertexFmt(int32 flags, uint32 numTexSets)
{
if(numTexSets > 4)
numTexSets = 4;
uint32 fmt = 0x5; // FLOAT3
if(flags & Geometry::NORMALS)
fmt |= 0x40; // NORMPACKED3
for(uint32 i = 0; i < numTexSets; i++)
fmt |= 0x500 << i*4; // FLOAT2
if(flags & Geometry::PRELIT)
fmt |= 0x1000000; // D3DCOLOR
return fmt;
}
uint32
getVertexFmtStride(uint32 fmt)
{
uint32 stride = 0;
uint32 v = fmt & 0xF;
uint32 n = (fmt >> 4) & 0xF;
stride += v == 4 ? 4 : 3*vertexFormatSizes[v];
stride += n == 4 ? 4 : 3*vertexFormatSizes[n];
if(fmt & 0x1000000)
stride += 4;
for(int i = 0; i < 4; i++){
uint32 t = (fmt >> (i*4 + 8)) & 0xF;
stride += t == 4 ? 4 : 2*vertexFormatSizes[t];
}
if(fmt & 0xE000000)
stride += 8;
return stride;
}
static void*
createVertexFmt(void *object, int32 offset, int32)
{
@@ -239,9 +435,8 @@ static void
readVertexFmt(Stream *stream, int32, void *object, int32 offset, int32)
{
uint32 fmt = stream->readU32();
// printf("vertexfmt: %X\n", fmt);
*PLUGINOFFSET(uint32, object, offset) = fmt;
// TODO: create and attach "vertex shader"
// TODO: ? create and attach "vertex shader"
}
static void
@@ -253,14 +448,15 @@ writeVertexFmt(Stream *stream, int32, void *object, int32 offset, int32)
static int32
getSizeVertexFmt(void*, int32, int32)
{
// TODO: make dependent on platform
if(rw::platform != PLATFORM_XBOX)
return -1;
return 4;
}
void
registerVertexFormatPlugin(void)
{
Geometry::registerPlugin(sizeof(uint32), ID_VERTEXFMT,
vertexFmtOffset = Geometry::registerPlugin(sizeof(uint32), ID_VERTEXFMT,
createVertexFmt, NULL, copyVertexFmt);
Geometry::registerPluginStream(ID_VERTEXFMT,
readVertexFmt,