Organized the project properly.

This commit is contained in:
Angelo Papenhoff
2014-12-23 15:59:14 +01:00
parent 0097487f9b
commit 179e521f91
14 changed files with 241 additions and 220 deletions

493
src/clump.cpp Normal file
View File

@@ -0,0 +1,493 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <fstream>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwobjects.h"
using namespace std;
namespace Rw {
Frame::Frame(void)
{
this->child = NULL;
this->next = NULL;
this->root = NULL;
constructPlugins();
}
Frame::Frame(Frame *f)
{
// TODO
copyPlugins(f);
}
Frame::~Frame(void)
{
destructPlugins();
}
Frame*
Frame::addChild(Frame *child)
{
if(this->child == NULL)
this->child = child;
else{
Frame *f;
for(f = this->child; f->next; f = f->next);
f->next = child;
}
child->next = NULL;
child->parent = this;
child->root = this->root;
return this;
}
Frame*
Frame::removeChild(void)
{
Frame *parent = (Frame*)this->parent;
if(parent->child == this)
parent->child = this->next;
else{
Frame *f;
for(f = parent->child; f; f = f->next)
if(f->next == this)
goto found;
// not found
found:
f->next = f->next->next;
}
this->parent = NULL;
this->next = this->root = NULL;
return this;
}
Frame*
Frame::forAllChildren(Callback cb, void *data)
{
for(Frame *f = this->child; f; f = f->next)
cb(f, data);
return this;
}
static Frame*
countCB(Frame *f, void *count)
{
(*(int32*)count)++;
f->forAllChildren(countCB, count);
return f;
}
int32
Frame::count(void)
{
int32 count = 1;
this->forAllChildren(countCB, (void*)&count);
return count;
}
static Frame*
sizeCB(Frame *f, void *size)
{
*(int32*)size += f->streamGetPluginSize();
f->forAllChildren(sizeCB, size);
return f;
}
static Frame**
makeFrameList(Frame *frame, Frame **flist)
{
*flist++ = frame;
if(frame->next)
flist = makeFrameList(frame->next, flist);
if(frame->child)
flist = makeFrameList(frame->child, flist);
return flist;
}
Clump::Clump(void)
{
this->numAtomics = 0;
this->numLights = 0;
this->numCameras = 0;
constructPlugins();
}
Clump::Clump(Clump *c)
{
this->numAtomics = c->numAtomics;
this->numLights = c->numLights;
this->numCameras = c->numCameras;
copyPlugins(c);
}
Clump::~Clump(void)
{
destructPlugins();
}
Clump*
Clump::streamRead(istream &stream)
{
uint32 length, version;
int32 buf[3];
Clump *clump;
assert(FindChunk(stream, ID_STRUCT, &length, &version));
clump = new Clump;
stream.read((char*)buf, length);
clump->numAtomics = buf[0];
clump->numLights = 0;
clump->numCameras = 0;
if(version >= 0x33000){
clump->numLights = buf[1];
clump->numCameras = buf[2];
}
// Frame list
Frame **frameList;
int32 numFrames;
clump->frameListStreamRead(stream, &frameList, &numFrames);
clump->parent = (void*)frameList[0];
// Geometry list
int32 numGeometries = 0;
assert(FindChunk(stream, ID_GEOMETRYLIST, NULL, NULL));
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
numGeometries = readInt32(stream);
Geometry **geometryList = new Geometry*[numGeometries];
for(int32 i = 0; i < numGeometries; i++){
assert(FindChunk(stream, ID_GEOMETRY, NULL, NULL));
geometryList[i] = Geometry::streamRead(stream);
}
// Atomics
clump->atomicList = new Atomic*[clump->numAtomics];
for(int32 i = 0; i < clump->numAtomics; i++){
assert(FindChunk(stream, ID_ATOMIC, NULL, NULL));
clump->atomicList[i] = Atomic::streamReadClump(stream,
frameList, geometryList);
clump->atomicList[i]->clump = clump;
}
// Lights
clump->lightList = new Light*[clump->numLights];
for(int32 i = 0; i < clump->numLights; i++){
int32 frm;
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
frm = readInt32(stream);
assert(FindChunk(stream, ID_LIGHT, NULL, NULL));
clump->lightList[i] = Light::streamRead(stream);
clump->lightList[i]->frame = frameList[frm];
clump->lightList[i]->clump = clump;
}
delete[] frameList;
clump->streamReadPlugins(stream);
return clump;
}
bool
Clump::streamWrite(ostream &stream)
{
int size = this->streamGetSize();
WriteChunkHeader(stream, ID_CLUMP, size);
int buf[3] = { this->numAtomics, this->numLights, this->numCameras };
size = Version >= 0x33000 ? 12 : 4;
WriteChunkHeader(stream, ID_STRUCT, size);
stream.write((char*)buf, size);
int32 numFrames = ((Frame*)this->parent)->count();
Frame **flist = new Frame*[numFrames];
makeFrameList((Frame*)this->parent, flist);
this->frameListStreamWrite(stream, flist, numFrames);
size = 12+4;
for(int32 i = 0; i < this->numAtomics; i++)
size += 12 + this->atomicList[i]->geometry->streamGetSize();
WriteChunkHeader(stream, ID_GEOMETRYLIST, size);
WriteChunkHeader(stream, ID_STRUCT, 4);
writeInt32(this->numAtomics, stream); // same as numGeometries
for(int32 i = 0; i < this->numAtomics; i++)
this->atomicList[i]->geometry->streamWrite(stream);
for(int32 i = 0; i < this->numAtomics; i++)
this->atomicList[i]->streamWriteClump(stream, flist, numFrames);
for(int32 i = 0; i < this->numLights; i++){
Light *l = this->lightList[i];
int frm = findPointer((void*)l->frame, (void**)flist,numFrames);
if(frm < 0)
return false;
WriteChunkHeader(stream, ID_STRUCT, 4);
writeInt32(frm, stream);
l->streamWrite(stream);
}
delete[] flist;
this->streamWritePlugins(stream);
return true;
}
struct FrameStreamData
{
float32 mat[9];
float32 pos[3];
int32 parent;
int32 matflag;
};
uint32
Clump::streamGetSize(void)
{
uint32 size = 0;
size += 12; // Struct
size += 4; // numAtomics
if(Version >= 0x33000)
size += 8; // numLights, numCameras
// frame list
int32 numFrames = ((Frame*)this->parent)->count();
size += 12 + 12 + 4 + numFrames*(sizeof(FrameStreamData)+12);
sizeCB((Frame*)this->parent, (void*)&size);
// geometry list
size += 12 + 12 + 4;
for(int32 i = 0; i < this->numAtomics; i++)
size += 12 + this->atomicList[i]->geometry->streamGetSize();
// atomics
for(int32 i = 0; i < this->numAtomics; i++)
size += 12 + this->atomicList[i]->streamGetSize();
// light
for(int32 i = 0; i < this->numAtomics; i++)
size += 16 + 12 + this->lightList[i]->streamGetSize();
size += 12 + this->streamGetPluginSize();
return size;
}
void
Clump::frameListStreamRead(istream &stream, Frame ***flp, int32 *nf)
{
FrameStreamData buf;
int32 numFrames = 0;
assert(FindChunk(stream, ID_FRAMELIST, NULL, NULL));
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
numFrames = readInt32(stream);
Frame **frameList = new Frame*[numFrames];
for(int32 i = 0; i < numFrames; i++){
Frame *f;
frameList[i] = f = new Frame;
stream.read((char*)&buf, sizeof(buf));
f->matrix[0] = buf.mat[0];
f->matrix[1] = buf.mat[1];
f->matrix[2] = buf.mat[2];
f->matrix[3] = 0.0f;
f->matrix[4] = buf.mat[3];
f->matrix[5] = buf.mat[4];
f->matrix[6] = buf.mat[5];
f->matrix[7] = 0.0f;
f->matrix[8] = buf.mat[6];
f->matrix[9] = buf.mat[7];
f->matrix[10] = buf.mat[8];
f->matrix[11] = 0.0f;
f->matrix[12] = buf.pos[0];
f->matrix[13] = buf.pos[1];
f->matrix[14] = buf.pos[2];
f->matrix[15] = 1.0f;
if(buf.parent >= 0)
frameList[buf.parent]->addChild(f);
f->matflag = buf.matflag;
}
for(int32 i = 0; i < numFrames; i++)
frameList[i]->streamReadPlugins(stream);
*nf = numFrames;
*flp = frameList;
}
void
Clump::frameListStreamWrite(ostream &stream, Frame **frameList, int32 numFrames)
{
FrameStreamData buf;
int size = 0, structsize = 0;
structsize = 4 + numFrames*sizeof(FrameStreamData);
size += 12 + structsize;
for(int32 i = 0; i < numFrames; i++)
size += 12 + frameList[i]->streamGetPluginSize();
WriteChunkHeader(stream, ID_FRAMELIST, size);
WriteChunkHeader(stream, ID_STRUCT, structsize);
writeUInt32(numFrames, stream);
for(int32 i = 0; i < numFrames; i++){
Frame *f = frameList[i];
buf.mat[0] = f->matrix[0];
buf.mat[1] = f->matrix[1];
buf.mat[2] = f->matrix[2];
buf.mat[3] = f->matrix[4];
buf.mat[4] = f->matrix[5];
buf.mat[5] = f->matrix[6];
buf.mat[6] = f->matrix[8];
buf.mat[7] = f->matrix[9];
buf.mat[8] = f->matrix[10];
buf.pos[0] = f->matrix[12];
buf.pos[1] = f->matrix[13];
buf.pos[2] = f->matrix[14];
buf.parent = findPointer((void*)f, (void**)frameList,numFrames);
buf.matflag = f->matflag;
stream.write((char*)&buf, sizeof(buf));
}
for(int32 i = 0; i < numFrames; i++)
frameList[i]->streamWritePlugins(stream);
}
Atomic::Atomic(void)
{
this->frame = NULL;
this->geometry = NULL;
constructPlugins();
}
Atomic::Atomic(Atomic *a)
{
//TODO
copyPlugins(a);
}
Atomic::~Atomic(void)
{
//TODO
destructPlugins();
}
Atomic*
Atomic::streamReadClump(istream &stream,
Frame **frameList, Geometry **geometryList)
{
int32 buf[4];
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
stream.read((char*)buf, 16);
Atomic *atomic = new Atomic;
atomic->frame = frameList[buf[0]];
atomic->geometry = geometryList[buf[1]];
atomic->streamReadPlugins(stream);
return atomic;
}
bool
Atomic::streamWriteClump(ostream &stream, Frame **frameList, int32 numFrames)
{
int32 buf[4] = { 0, 0, 5, 0 };
Clump *c = this->clump;
if(c == NULL)
return false;
WriteChunkHeader(stream, ID_ATOMIC, this->streamGetSize());
WriteChunkHeader(stream, ID_STRUCT, 16);
buf[0] = findPointer((void*)this->frame, (void**)frameList, numFrames);
// TODO
for(buf[1] = 0; buf[1] < c->numAtomics; buf[1]++)
if(c->atomicList[buf[1]]->geometry == this->geometry)
goto foundgeo;
return false;
foundgeo:
stream.write((char*)buf, sizeof(buf));
this->streamWritePlugins(stream);
return true;
}
uint32
Atomic::streamGetSize(void)
{
return 12 + 16 + 12 + this->streamGetPluginSize();
}
Light::Light(void)
{
this->frame = NULL;
constructPlugins();
}
Light::Light(Light *l)
{
// TODO
copyPlugins(l);
}
Light::~Light(void)
{
destructPlugins();
}
struct LightChunkData
{
float32 radius;
float32 red, green, blue;
float32 minusCosAngle;
uint16 flags;
uint16 type;
};
Light*
Light::streamRead(istream &stream)
{
LightChunkData buf;
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
Light *light = new Light;
stream.read((char*)&buf, sizeof(LightChunkData));
light->radius = buf.radius;
light->color[0] = buf.red;
light->color[1] = buf.green;
light->color[2] = buf.blue;
light->color[3] = 1.0f;
light->minusCosAngle = buf.minusCosAngle;
light->flags = (uint8)buf.flags;
light->subType = (uint8)buf.type;
light->streamReadPlugins(stream);
return light;
}
bool
Light::streamWrite(ostream &stream)
{
LightChunkData buf;
WriteChunkHeader(stream, ID_LIGHT, this->streamGetSize());
WriteChunkHeader(stream, ID_STRUCT, sizeof(LightChunkData));
buf.radius = this->radius;
buf.red = this->color[0];
buf.green = this->color[1];
buf.blue = this->color[2];
buf.minusCosAngle = this->minusCosAngle;
buf.flags = this->flags;
buf.type = this->subType;
stream.write((char*)&buf, sizeof(LightChunkData));
this->streamWritePlugins(stream);
return true;
}
uint32
Light::streamGetSize(void)
{
return 12 + sizeof(LightChunkData) + 12 + this->streamGetPluginSize();
}
}

464
src/geometry.cpp Normal file
View File

@@ -0,0 +1,464 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <fstream>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwobjects.h"
using namespace std;
namespace Rw {
Geometry::Geometry(int32 numVerts, int32 numTris, uint32 flags)
{
this->geoflags = flags & 0xFF00FFFF;
this->numTexCoordSets = (flags & 0xFF0000) >> 16;
if(this->numTexCoordSets == 0 && (this->geoflags & TEXTURED))
this->numTexCoordSets = 1;
this->numTriangles = numTris;
this->numVertices = numVerts;
this->numMorphTargets = 1;
this->colors = NULL;
for(int32 i = 0; i < this->numTexCoordSets; i++)
this->texCoords[i] = NULL;
this->triangles = NULL;
if(!(this->geoflags & 0xFF000000)){
if(this->geoflags & PRELIT)
this->colors = new uint8[4*this->numVertices];
if((this->geoflags & TEXTURED) || (this->geoflags & TEXTURED2))
for(int32 i = 0; i < this->numTexCoordSets; i++)
this->texCoords[i] =
new float32[2*this->numVertices];
this->triangles = new uint16[4*this->numTriangles];
}
this->morphTargets = new MorphTarget[1];
MorphTarget *m = this->morphTargets;
m->vertices = NULL;
m->normals = NULL;
if(!(this->geoflags & 0xFF000000)){
m->vertices = new float32[3*this->numVertices];
if(this->geoflags & NORMALS)
m->normals = new float32[3*this->numVertices];
}
this->numMaterials = 0;
this->materialList = NULL;
this->meshHeader = NULL;
this->refCount = 1;
this->constructPlugins();
}
Geometry::~Geometry(void)
{
this->destructPlugins();
delete[] this->colors;
for(int32 i = 0; i < this->numTexCoordSets; i++)
delete[] this->texCoords[i];
delete[] this->triangles;
for(int32 i = 0; i < this->numMorphTargets; i++){
MorphTarget *m = &this->morphTargets[i];
delete[] m->vertices;
delete[] m->normals;
}
delete[] this->morphTargets;
if(this->meshHeader){
for(uint32 i = 0; i < this->meshHeader->numMeshes; i++)
delete[] this->meshHeader->mesh[i].indices;
delete[] this->meshHeader->mesh;
delete this->meshHeader;
}
for(int32 i = 0; i < this->numMaterials; i++)
this->materialList[i]->decRef();
delete[] this->materialList;
}
void
Geometry::decRef(void)
{
this->refCount--;
if(this->refCount)
delete this;
}
struct GeoStreamData
{
uint32 flags;
int32 numTriangles;
int32 numVertices;
int32 numMorphTargets;
};
Geometry*
Geometry::streamRead(istream &stream)
{
uint32 version;
GeoStreamData buf;
assert(FindChunk(stream, ID_STRUCT, NULL, &version));
stream.read((char*)&buf, sizeof(buf));
Geometry *geo = new Geometry(buf.numVertices,
buf.numTriangles, buf.flags);
geo->addMorphTargets(buf.numMorphTargets-1);
// skip surface properties
if(version < 0x34000)
stream.seekg(12, ios::cur);
if(!(geo->geoflags & 0xFF000000)){
if(geo->geoflags & PRELIT)
stream.read((char*)geo->colors, 4*geo->numVertices);
if((geo->geoflags & TEXTURED) || (geo->geoflags & TEXTURED2))
for(int32 i = 0; i < geo->numTexCoordSets; i++)
stream.read((char*)geo->texCoords[i],
2*geo->numVertices*4);
stream.read((char*)geo->triangles, 4*geo->numTriangles*2);
}
for(int32 i = 0; i < geo->numMorphTargets; i++){
MorphTarget *m = &geo->morphTargets[i];
stream.read((char*)m->boundingSphere, 4*4);
int32 hasVertices = readInt32(stream);
int32 hasNormals = readInt32(stream);
if(hasVertices)
stream.read((char*)m->vertices, 3*geo->numVertices*4);
if(hasNormals)
stream.read((char*)m->normals, 3*geo->numVertices*4);
}
assert(FindChunk(stream, ID_MATLIST, NULL, NULL));
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
geo->numMaterials = readInt32(stream);
geo->materialList = new Material*[geo->numMaterials];
stream.seekg(geo->numMaterials*4, ios::cur); // unused (-1)
for(int32 i = 0; i < geo->numMaterials; i++){
assert(FindChunk(stream, ID_MATERIAL, NULL, NULL));
geo->materialList[i] = Material::streamRead(stream);
}
geo->streamReadPlugins(stream);
return geo;
}
static uint32
geoStructSize(Geometry *geo)
{
uint32 size = 0;
size += sizeof(GeoStreamData);
if(Version < 0x34000)
size += 12; // surface properties
if(!(geo->geoflags & 0xFF000000)){
if(geo->geoflags&geo->PRELIT)
size += 4*geo->numVertices;
if((geo->geoflags & geo->TEXTURED) ||
(geo->geoflags & geo->TEXTURED2))
for(int32 i = 0; i < geo->numTexCoordSets; i++)
size += 2*geo->numVertices*4;
size += 4*geo->numTriangles*2;
}
for(int32 i = 0; i < geo->numMorphTargets; i++){
MorphTarget *m = &geo->morphTargets[i];
size += 4*4 + 2*4; // bounding sphere and bools
if(m->vertices)
size += 3*geo->numVertices*4;
if(m->normals)
size += 3*geo->numVertices*4;
}
return size;
}
bool
Geometry::streamWrite(ostream &stream)
{
GeoStreamData buf;
uint32 size;
static float32 fbuf[3] = { 1.0f, 1.0f, 1.0f };
WriteChunkHeader(stream, ID_GEOMETRY, this->streamGetSize());
WriteChunkHeader(stream, ID_STRUCT, geoStructSize(this));
buf.flags = this->geoflags | this->numTexCoordSets << 16;
buf.numTriangles = this->numTriangles;
buf.numVertices = this->numVertices;
buf.numMorphTargets = this->numMorphTargets;
stream.write((char*)&buf, sizeof(buf));
if(Version < 0x34000)
stream.write((char*)fbuf, sizeof(fbuf));
if(!(this->geoflags & 0xFF000000)){
if(this->geoflags & PRELIT)
stream.write((char*)this->colors, 4*this->numVertices);
if((this->geoflags & TEXTURED) || (this->geoflags & TEXTURED2))
for(int32 i = 0; i < this->numTexCoordSets; i++)
stream.write((char*)this->texCoords[i],
2*this->numVertices*4);
stream.write((char*)this->triangles, 4*this->numTriangles*2);
}
for(int32 i = 0; i < this->numMorphTargets; i++){
MorphTarget *m = &this->morphTargets[i];
stream.write((char*)m->boundingSphere, 4*4);
writeInt32(m->vertices != NULL, stream);
writeInt32(m->normals != NULL, stream);
if(m->vertices)
stream.write((char*)m->vertices, 3*this->numVertices*4);
if(m->normals)
stream.write((char*)m->normals, 3*this->numVertices*4);
}
size = 12 + 4;
for(int32 i = 0; i < this->numMaterials; i++)
size += 4 + 12 + this->materialList[i]->streamGetSize();
WriteChunkHeader(stream, ID_MATLIST, size);
WriteChunkHeader(stream, ID_STRUCT, 4 + this->numMaterials*4);
writeInt32(this->numMaterials, stream);
for(int32 i = 0; i < this->numMaterials; i++)
writeInt32(-1, stream);
for(int32 i = 0; i < this->numMaterials; i++)
this->materialList[i]->streamWrite(stream);
this->streamWritePlugins(stream);
return true;
}
uint32
Geometry::streamGetSize(void)
{
uint32 size = 0;
size += 12 + geoStructSize(this);
size += 12 + 12 + 4;
for(int32 i = 0; i < this->numMaterials; i++)
size += 4 + 12 + this->materialList[i]->streamGetSize();
size += 12 + this->streamGetPluginSize();
return size;
}
void
Geometry::addMorphTargets(int32 n)
{
if(n == 0)
return;
MorphTarget *morphTargets = new MorphTarget[this->numMorphTargets+n];
memcpy(morphTargets, this->morphTargets,
this->numMorphTargets*sizeof(MorphTarget));
delete[] this->morphTargets;
this->morphTargets = morphTargets;
for(int32 i = this->numMorphTargets; i < n; i++){
MorphTarget *m = &morphTargets[i];
m->vertices = NULL;
m->normals = NULL;
if(!(this->geoflags & 0xFF000000)){
m->vertices = new float32[3*this->numVertices];
if(this->geoflags & NORMALS)
m->normals = new float32[3*this->numVertices];
}
}
this->numMorphTargets += n;
}
Material::Material(void)
{
this->texture = NULL;
memset(this->color, 0xFF, 4);
surfaceProps[0] = surfaceProps[1] = surfaceProps[2] = 1.0f;
this->refCount = 1;
this->constructPlugins();
}
Material::Material(Material *m)
{
m->color[0] = this->color[0];
m->color[1] = this->color[1];
m->color[2] = this->color[2];
m->color[3] = this->color[3];
m->surfaceProps[0] = this->surfaceProps[0];
m->surfaceProps[1] = this->surfaceProps[1];
m->surfaceProps[2] = this->surfaceProps[2];
m->texture = this->texture;
if(m->texture)
m->texture->refCount++;
this->copyPlugins(m);
}
Material::~Material(void)
{
this->destructPlugins();
if(this->texture)
this->texture->decRef();
}
void
Material::decRef(void)
{
this->refCount--;
if(this->refCount)
delete this;
}
struct MatStreamData
{
int32 flags; // unused according to RW
uint8 color[4];
int32 unused;
int32 textured;
float32 surfaceProps[3];
};
Material*
Material::streamRead(istream &stream)
{
uint32 length;
MatStreamData buf;
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
stream.read((char*)&buf, sizeof(buf));
Material *mat = new Material;
mat->color[0] = buf.color[0];
mat->color[1] = buf.color[1];
mat->color[2] = buf.color[2];
mat->color[3] = buf.color[3];
mat->surfaceProps[0] = buf.surfaceProps[0];
mat->surfaceProps[1] = buf.surfaceProps[1];
mat->surfaceProps[2] = buf.surfaceProps[2];
if(buf.textured){
assert(FindChunk(stream, ID_TEXTURE, &length, NULL));
mat->texture = Texture::streamRead(stream);
}
mat->streamReadPlugins(stream);
return mat;
}
bool
Material::streamWrite(ostream &stream)
{
MatStreamData buf;
WriteChunkHeader(stream, ID_MATERIAL, this->streamGetSize());
WriteChunkHeader(stream, ID_STRUCT, sizeof(MatStreamData));
buf.color[0] = this->color[0];
buf.color[1] = this->color[1];
buf.color[2] = this->color[2];
buf.color[3] = this->color[3];
buf.surfaceProps[0] = this->surfaceProps[0];
buf.surfaceProps[1] = this->surfaceProps[1];
buf.surfaceProps[2] = this->surfaceProps[2];
buf.flags = 0;
buf.unused = 0;
buf.textured = this->texture != NULL;
stream.write((char*)&buf, sizeof(buf));
if(this->texture)
this->texture->streamWrite(stream);
this->streamWritePlugins(stream);
return true;
}
uint32
Material::streamGetSize(void)
{
uint32 size = 0;
size += 12 + sizeof(MatStreamData);
if(this->texture)
size += 12 + this->texture->streamGetSize();
size += 12 + this->streamGetPluginSize();
return size;
}
Texture::Texture(void)
{
memset(this->name, 0, 32);
memset(this->mask, 0, 32);
this->filterAddressing = (WRAP << 12) | (WRAP << 8) | NEAREST;
this->refCount = 1;
this->constructPlugins();
}
Texture::~Texture(void)
{
this->destructPlugins();
}
void
Texture::decRef(void)
{
this->refCount--;
if(this->refCount)
delete this;
}
Texture*
Texture::streamRead(istream &stream)
{
uint32 length;
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
Texture *tex = new Texture;
tex->filterAddressing = readUInt16(stream);
stream.seekg(2, ios::cur);
assert(FindChunk(stream, ID_STRING, &length, NULL));
stream.read(tex->name, length);
assert(FindChunk(stream, ID_STRING, &length, NULL));
stream.read(tex->mask, length);
tex->streamReadPlugins(stream);
return tex;
}
bool
Texture::streamWrite(ostream &stream)
{
int size;
WriteChunkHeader(stream, ID_TEXTURE, this->streamGetSize());
WriteChunkHeader(stream, ID_STRUCT, 4);
writeUInt32(this->filterAddressing, stream);
size = strnlen(this->name, 32)+3 & ~3;
if(size < 4)
size = 4;
WriteChunkHeader(stream, ID_STRING, size);
stream.write(this->name, size);
size = strnlen(this->mask, 32)+3 & ~3;
if(size < 4)
size = 4;
WriteChunkHeader(stream, ID_STRING, size);
stream.write(this->mask, size);
this->streamWritePlugins(stream);
return true;
}
uint32
Texture::streamGetSize(void)
{
uint32 size = 0;
int strsize;
size += 12 + 4;
size += 12 + 12;
strsize = strnlen(this->name, 32)+3 & ~3;
size += strsize < 4 ? 4 : strsize;
strsize = strnlen(this->mask, 32)+3 & ~3;
size += strsize < 4 ? 4 : strsize;
size += 12 + this->streamGetPluginSize();
return size;
}
}

71
src/ogl.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <fstream>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwobjects.h"
#include "rwogl.h"
using namespace std;
namespace Rw {
void*
DestroyNativeDataOGL(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
OGLInstanceDataHeader *header =
(OGLInstanceDataHeader*)geometry->instData;
delete[] header->attribs;
delete[] header->data;
delete header;
return object;
}
void
ReadNativeDataOGL(istream &stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
OGLInstanceDataHeader *header = new OGLInstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_OGL;
header->numAttribs = readUInt32(stream);
header->attribs = new OGLAttrib[header->numAttribs];
stream.read((char*)header->attribs,
header->numAttribs*sizeof(OGLAttrib));
// Any better way to find out the size? (header length can be wrong)
header->dataSize = header->attribs[0].stride*geometry->numVertices;
header->data = new uint8[header->dataSize];
stream.read((char*)header->data, header->dataSize);
}
void
WriteNativeDataOGL(ostream &stream, int32 len, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
OGLInstanceDataHeader *header =
(OGLInstanceDataHeader*)geometry->instData;
writeUInt32(header->numAttribs, stream);
stream.write((char*)header->attribs,
header->numAttribs*sizeof(OGLAttrib));
stream.write((char*)header->data, header->dataSize);
}
int32
GetSizeNativeDataOGL(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
OGLInstanceDataHeader *header =
(OGLInstanceDataHeader*)geometry->instData;
return 4 + header->numAttribs*sizeof(OGLAttrib) + header->dataSize;
}
}

265
src/plugins.cpp Normal file
View File

@@ -0,0 +1,265 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwobjects.h"
#include "rwps2.h"
#include "rwogl.h"
using namespace std;
using namespace Rw;
//
// Frame
//
// Node Name
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, 17);
return dst;
}
static void*
destroyNodeName(void *object, int32, int32)
{
return object;
}
static void
readNodeName(istream &stream, int32 len, void *object, int32 offset, int32)
{
char *name = PLUGINOFFSET(char, object, offset);
stream.read(name, len);
name[len] = '\0';
}
static void
writeNodeName(ostream &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)
{
char *name = PLUGINOFFSET(char, object, offset);
int32 len = strlen(name);
return len > 0 ? len : -1;
}
void
registerNodeNamePlugin(void)
{
Frame::registerPlugin(18, 0x253f2fe, (Constructor)createNodeName,
(Destructor)destroyNodeName,
(CopyConstructor)copyNodeName);
Frame::registerPluginStream(0x253f2fe, (StreamRead)readNodeName,
(StreamWrite)writeNodeName,
(StreamGetSize)getSizeNodeName);
}
//
// Geometry
//
// Mesh
static void
readMesh(istream &stream, int32 len, void *object, int32, int32)
{
Geometry *geo = (Geometry*)object;
int32 indbuf[256];
uint32 buf[3];
stream.read((char*)buf, 12);
geo->meshHeader = new MeshHeader;
geo->meshHeader->flags = buf[0];
geo->meshHeader->numMeshes = buf[1];
geo->meshHeader->totalIndices = buf[2];
geo->meshHeader->mesh = new Mesh[geo->meshHeader->numMeshes];
Mesh *mesh = geo->meshHeader->mesh;
bool hasData = len > 12+geo->meshHeader->numMeshes*8;
for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){
stream.read((char*)buf, 8);
mesh->numIndices = buf[0];
mesh->material = geo->materialList[buf[1]];
mesh->indices = NULL;
if(geo->geoflags & Geometry::NATIVE){
// OpenGL stores uint16 indices here
if(hasData){
mesh->indices = new uint16[mesh->numIndices];
stream.read((char*)mesh->indices,
mesh->numIndices*2);
}
}else{
mesh->indices = new uint16[mesh->numIndices];
uint16 *ind = mesh->indices;
int32 numIndices = mesh->numIndices;
for(; numIndices > 0; numIndices -= 256){
int32 n = numIndices < 256 ? numIndices : 256;
stream.read((char*)indbuf, n*4);
for(int32 j = 0; j < n; j++)
ind[j] = indbuf[j];
ind += n;
}
}
mesh++;
}
}
static void
writeMesh(ostream &stream, int32, void *object, int32, int32)
{
Geometry *geo = (Geometry*)object;
int32 indbuf[256];
uint32 buf[3];
buf[0] = geo->meshHeader->flags;
buf[1] = geo->meshHeader->numMeshes;
buf[2] = geo->meshHeader->totalIndices;
stream.write((char*)buf, 12);
Mesh *mesh = geo->meshHeader->mesh;
for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){
buf[0] = mesh->numIndices;
buf[1] = findPointer((void*)mesh->material,
(void**)geo->materialList,
geo->numMaterials);
stream.write((char*)buf, 8);
if(geo->geoflags & Geometry::NATIVE){
if(mesh->indices)
stream.write((char*)mesh->indices,
mesh->numIndices*2);
}else{
uint16 *ind = mesh->indices;
int32 numIndices = mesh->numIndices;
for(; numIndices > 0; numIndices -= 256){
int32 n = numIndices < 256 ? numIndices : 256;
for(int32 j = 0; j < n; j++)
indbuf[j] = ind[j];
stream.write((char*)indbuf, n*4);
ind += n;
}
}
mesh++;
}
}
static int32
getSizeMesh(void *object, int32)
{
Geometry *geo = (Geometry*)object;
if(geo->meshHeader == NULL)
return -1;
int32 size = 12 + geo->meshHeader->numMeshes*8;
if(geo->geoflags & Geometry::NATIVE){
if(geo->meshHeader[0].mesh->indices)
size += geo->meshHeader->totalIndices*2;
}else{
size += geo->meshHeader->totalIndices*4;
}
return size;
}
void
registerMeshPlugin(void)
{
Geometry::registerPlugin(0, 0x50E, NULL, NULL, NULL);
Geometry::registerPluginStream(0x50E, (StreamRead)readMesh,
(StreamWrite)writeMesh,
(StreamGetSize)getSizeMesh);
}
// Native Data
static void*
destroyNativeData(void *object, int32 offset, int32 size)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == NULL)
return object;
if(geometry->instData->platform == PLATFORM_PS2)
return DestroyNativeDataPS2(object, offset, size);
if(geometry->instData->platform == PLATFORM_OGL)
return DestroyNativeDataOGL(object, offset, size);
return object;
}
static void
readNativeData(istream &stream, int32 len, void *object, int32 o, int32 s)
{
ChunkHeaderInfo header;
uint32 libid;
uint32 platform;
// ugly hack to find out platform
stream.seekg(-4, ios::cur);
libid = readUInt32(stream);
ReadChunkHeaderInfo(stream, &header);
if(header.type == ID_STRUCT &&
LibraryIDPack(header.version, header.build) == libid){
// must be PS2 or Xbox
platform = readUInt32(stream);
stream.seekg(-16, ios::cur);
if(platform == PLATFORM_PS2)
ReadNativeDataPS2(stream, len, object, o, s);
else if(platform == PLATFORM_XBOX)
stream.seekg(len, ios::cur);
}else{
stream.seekg(-12, ios::cur);
ReadNativeDataOGL(stream, len, object, o, s);
}
}
static void
writeNativeData(ostream &stream, int32 len, void *object, int32 o, int32 s)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == NULL)
return;
if(geometry->instData->platform == PLATFORM_PS2)
WriteNativeDataPS2(stream, len, object, o, s);
else if(geometry->instData->platform == PLATFORM_OGL)
WriteNativeDataOGL(stream, len, object, o, s);
}
static int32
getSizeNativeData(void *object, int32 offset, int32 size)
{
Geometry *geometry = (Geometry*)object;
if(geometry->instData == NULL)
return -1;
if(geometry->instData->platform == PLATFORM_PS2)
return GetSizeNativeDataPS2(object, offset, size);
else if(geometry->instData->platform == PLATFORM_XBOX)
return -1;
else if(geometry->instData->platform == PLATFORM_OGL)
return GetSizeNativeDataOGL(object, offset, size);
return -1;
}
void
registerNativeDataPlugin(void)
{
Geometry::registerPlugin(0, 0x510, NULL, destroyNativeData, NULL);
Geometry::registerPluginStream(0x510, (StreamRead)readNativeData,
(StreamWrite)writeNativeData,
(StreamGetSize)getSizeNativeData);
}

92
src/ps2.cpp Normal file
View File

@@ -0,0 +1,92 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <fstream>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwobjects.h"
#include "rwps2.h"
using namespace std;
namespace Rw {
void*
DestroyNativeDataPS2(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_PS2);
PS2InstanceDataHeader *header =
(PS2InstanceDataHeader*)geometry->instData;
for(uint32 i = 0; i < header->numMeshes; i++)
delete[] header->instanceMeshes[i].data;
delete[] header->instanceMeshes;
delete header;
return object;
}
void
ReadNativeDataPS2(istream &stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
assert(readUInt32(stream) == PLATFORM_PS2);
PS2InstanceDataHeader *header = new PS2InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_PS2;
assert(geometry->meshHeader != NULL);
header->numMeshes = geometry->meshHeader->numMeshes;
header->instanceMeshes = new PS2InstanceData[header->numMeshes];
for(uint32 i = 0; i < header->numMeshes; i++){
PS2InstanceData *instance = &header->instanceMeshes[i];
uint32 buf[2];
stream.read((char*)buf, 8);
instance->dataSize = buf[0];
instance->noRefChain = buf[1];
instance->data = new uint8[instance->dataSize];
stream.read((char*)instance->data, instance->dataSize);
}
}
void
WriteNativeDataPS2(ostream &stream, int32 len, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
WriteChunkHeader(stream, ID_STRUCT, len-12);
assert(geometry->instData->platform == PLATFORM_PS2);
writeUInt32(PLATFORM_PS2, stream);
assert(geometry->instData != NULL);
PS2InstanceDataHeader *header =
(PS2InstanceDataHeader*)geometry->instData;
for(uint32 i = 0; i < header->numMeshes; i++){
PS2InstanceData *instance = &header->instanceMeshes[i];
uint32 buf[2];
buf[0] = instance->dataSize;
buf[1] = instance->noRefChain;
stream.write((char*)buf, 8);
stream.write((char*)instance->data, instance->dataSize);
}
}
int32
GetSizeNativeDataPS2(void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
int32 size = 16;
assert(geometry->instData->platform == PLATFORM_PS2);
assert(geometry->instData != NULL);
PS2InstanceDataHeader *header =
(PS2InstanceDataHeader*)geometry->instData;
for(uint32 i = 0; i < header->numMeshes; i++){
PS2InstanceData *instance = &header->instanceMeshes[i];
size += 8;
size += instance->dataSize;
}
return size;
}
}

175
src/rwbase.cpp Normal file
View File

@@ -0,0 +1,175 @@
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <fstream>
#include "rwbase.h"
#include "rwplugin.h"
using namespace std;
namespace Rw {
int Version = 0x36003;
int Build = 0xFFFF;
uint32
writeInt8(int8 tmp, ostream &rw)
{
rw.write((char*)&tmp, sizeof(int8));
return sizeof(int8);
}
uint32
writeUInt8(uint8 tmp, ostream &rw)
{
rw.write((char*)&tmp, sizeof(uint8));
return sizeof(uint8);
}
uint32
writeInt16(int16 tmp, ostream &rw)
{
rw.write((char*)&tmp, sizeof(int16));
return sizeof(int16);
}
uint32
writeUInt16(uint16 tmp, ostream &rw)
{
rw.write((char*)&tmp, sizeof(uint16));
return sizeof(uint16);
}
uint32
writeInt32(int32 tmp, ostream &rw)
{
rw.write((char*)&tmp, sizeof(int32));
return sizeof(int32);
}
uint32
writeUInt32(uint32 tmp, ostream &rw)
{
rw.write((char*)&tmp, sizeof(uint32));
return sizeof(uint32);
}
uint32
writeFloat32(float32 tmp, ostream &rw)
{
rw.write((char*)&tmp, sizeof(float32));
return sizeof(float32);
}
uint8
readUInt8(istream &rw)
{
uint8 tmp;
rw.read((char*)&tmp, sizeof(uint8));
return tmp;
}
int16
readInt16(istream &rw)
{
int16 tmp;
rw.read((char*)&tmp, sizeof(int16));
return tmp;
}
uint16
readUInt16(istream &rw)
{
uint16 tmp;
rw.read((char*)&tmp, sizeof(uint16));
return tmp;
}
int32
readInt32(istream &rw)
{
int32 tmp;
rw.read((char*)&tmp, sizeof(int32));
return tmp;
}
uint32
readUInt32(istream &rw)
{
uint32 tmp;
rw.read((char*)&tmp, sizeof(uint32));
return tmp;
}
float32
readFloat32(istream &rw)
{
float32 tmp;
rw.read((char*)&tmp, sizeof(float32));
return tmp;
}
bool
WriteChunkHeader(ostream &s, int32 type, int32 size)
{
struct {
int32 type, size;
uint32 id;
} buf = { type, size, LibraryIDPack(Version, Build) };
s.write((char*)&buf, 12);
return true;
}
bool
ReadChunkHeaderInfo(istream &s, ChunkHeaderInfo *header)
{
struct {
int32 type, size;
uint32 id;
} buf;
s.read((char*)&buf, 12);
if(s.eof())
return false;
assert(header != NULL);
header->type = buf.type;
header->length = buf.size;
header->version = LibraryIDUnpackVersion(buf.id);
header->build = LibraryIDUnpackBuild(buf.id);
return true;
}
bool
FindChunk(istream &s, uint32 type, uint32 *length, uint32 *version)
{
ChunkHeaderInfo header;
while(ReadChunkHeaderInfo(s, &header)){
if(header.type == ID_NAOBJECT)
return false;
if(header.type == type){
if(length)
*length = header.length;
if(version)
*version = header.version;
return true;
}
s.seekg(header.length, ios::cur);
}
return false;
}
int32
findPointer(void *p, void **list, int32 num)
{
int i;
for(i = 0; i < num; i++)
if(list[i] == p)
goto found;
return -1;
found:
return i;
}
}

111
src/rwbase.h Normal file
View File

@@ -0,0 +1,111 @@
namespace Rw {
typedef char int8;
typedef short int16;
typedef int int32;
typedef long long int64;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long uint64;
typedef float float32;
typedef int32 bool32;
typedef uint8 byte;
typedef uint32 uint;
uint32 writeInt8(int8 tmp, std::ostream &rw);
uint32 writeUInt8(uint8 tmp, std::ostream &rw);
uint32 writeInt16(int16 tmp, std::ostream &rw);
uint32 writeUInt16(uint16 tmp, std::ostream &rw);
uint32 writeInt32(int32 tmp, std::ostream &rw);
uint32 writeUInt32(uint32 tmp, std::ostream &rw);
uint32 writeFloat32(float32 tmp, std::ostream &rw);
int8 readInt8(std::istream &rw);
uint8 readUInt8(std::istream &rw);
int16 readInt16(std::istream &rw);
uint16 readUInt16(std::istream &rw);
int32 readInt32(std::istream &rw);
uint32 readUInt32(std::istream &rw);
float32 readFloat32(std::istream &rw);
enum Platform
{
PLATFORM_OGL = 2,
PLATFORM_PS2 = 4,
PLATFORM_XBOX = 5,
PLATFORM_D3D8 = 8,
PLATFORM_D3D9 = 9
};
enum PluginID
{
// Core
ID_NAOBJECT = 0x0,
ID_STRUCT = 0x1,
ID_STRING = 0x2,
ID_EXTENSION = 0x3,
ID_CAMERA = 0x5,
ID_TEXTURE = 0x6,
ID_MATERIAL = 0x7,
ID_MATLIST = 0x8,
ID_FRAMELIST = 0xE,
ID_GEOMETRY = 0xF,
ID_CLUMP = 0x10,
ID_LIGHT = 0x12,
ID_ATOMIC = 0x14,
ID_TEXTURENATIVE = 0x15,
ID_TEXDICTIONARY = 0x16,
ID_GEOMETRYLIST = 0x1A,
ID_ANIMANIMATION = 0x1B,
ID_RIGHTTORENDER = 0x1F,
ID_UVANIMDICT = 0x2B,
};
extern int Version;
extern int Build;
inline uint32
LibraryIDPack(int version, int build)
{
if(build){
version -= 0x30000;
return (version&0xFFC0) << 14 | (version&0x3F) << 16 |
(build & 0xFFFF);
}
return version>>8;
}
inline int
LibraryIDUnpackVersion(uint32 libid)
{
if(libid & 0xFFFF0000)
return (libid>>14 & 0x3FF00) |
(libid>>16 & 0x3F) |
0x30000;
else
return libid<<8;
}
inline int
LibraryIDUnpackBuild(uint32 libid)
{
if(libid & 0xFFFF0000)
return libid & 0xFFFF;
else
return 0;
}
struct ChunkHeaderInfo
{
uint32 type;
uint32 length;
uint32 version, build;
};
// TODO?: make these methods of ChunkHeaderInfo?
bool WriteChunkHeader(std::ostream &s, int32 type, int32 size);
bool ReadChunkHeaderInfo(std::istream &s, ChunkHeaderInfo *header);
bool FindChunk(std::istream &s, uint32 type, uint32 *length, uint32 *version);
int32 findPointer(void *p, void **list, int32 num);
}

213
src/rwobjects.h Normal file
View File

@@ -0,0 +1,213 @@
namespace Rw {
struct Object
{
uint8 type;
uint8 subType;
uint8 flags;
void *parent;
};
// TODO: raster, link into texdict
struct Texture : PluginBase<Texture>
{
char name[32];
char mask[32];
uint32 filterAddressing;
int32 refCount;
Texture(void);
~Texture(void);
void decRef(void);
static Texture *streamRead(std::istream &stream);
bool streamWrite(std::ostream &stream);
uint32 streamGetSize(void);
enum FilterMode {
NEAREST = 1,
LINEAR,
MIPNEAREST,
MIPLINEAR,
LINEARMIPNEAREST,
LINEARMIPLINEAR
};
enum Addressing {
WRAP = 1,
MIRROR,
CLAMP,
BORDER
};
};
struct Material : PluginBase<Material>
{
Texture *texture;
uint8 color[4];
float32 surfaceProps[3];
int32 refCount;
Material(void);
Material(Material *m);
void decRef(void);
~Material(void);
static Material *streamRead(std::istream &stream);
bool streamWrite(std::ostream &stream);
uint32 streamGetSize(void);
};
struct Mesh
{
uint16 *indices;
uint32 numIndices;
Material *material;
};
struct MeshHeader
{
uint32 flags;
uint16 numMeshes;
// RW has uint16 serialNum here
uint32 totalIndices;
Mesh *mesh; // RW has a byte offset here
};
struct MorphTarget
{
float32 boundingSphere[4];
float32 *vertices;
float32 *normals;
};
struct InstanceDataHeader
{
uint32 platform;
};
struct Geometry : PluginBase<Geometry>, Object
{
uint32 geoflags;
int32 numTriangles;
int32 numVertices;
int32 numMorphTargets;
int32 numTexCoordSets;
uint16 *triangles;
uint8 *colors;
float32 *texCoords[8];
MorphTarget *morphTargets;
int32 numMaterials;
Material **materialList;
MeshHeader *meshHeader;
InstanceDataHeader *instData;
int32 refCount;
Geometry(int32 numVerts, int32 numTris, uint32 flags);
void decRef(void);
~Geometry(void);
static Geometry *streamRead(std::istream &stream);
bool streamWrite(std::ostream &stream);
uint32 streamGetSize(void);
void addMorphTargets(int32 n);
enum Flags
{
TRISTRIP = 0x01,
POSITIONS = 0x02,
TEXTURED = 0x04,
PRELIT = 0x08,
NORMALS = 0x10,
LIGHT = 0x20,
MODULATE = 0x40,
TEXTURED2 = 0x80,
NATIVE = 0x01000000,
NATIVEINSTANCE = 0x02000000
};
};
struct Frame : PluginBase<Frame>, Object
{
typedef Frame *(*Callback)(Frame *f, void *data);
float32 matrix[16];
float32 ltm[16];
Frame *child;
Frame *next;
Frame *root;
// temporary
int32 matflag;
Frame(void);
Frame(Frame *f);
~Frame(void);
Frame *addChild(Frame *f);
Frame *removeChild(void);
Frame *forAllChildren(Callback cb, void *data);
int32 count(void);
};
struct Clump;
struct Light : PluginBase<Light>, Object
{
Frame *frame;
float32 radius;
float32 color[4];
float32 minusCosAngle;
Clump *clump;
Light(void);
Light(Light *l);
~Light(void);
static Light *streamRead(std::istream &stream);
bool streamWrite(std::ostream &stream);
uint32 streamGetSize(void);
};
struct Atomic : PluginBase<Atomic>, Object
{
Frame *frame;
Geometry *geometry;
Clump *clump;
Atomic(void);
Atomic(Atomic *a);
~Atomic(void);
static Atomic *streamReadClump(std::istream &stream,
Frame **frameList, Geometry **geometryList);
bool streamWriteClump(std::ostream &stream,
Frame **frameList, int32 numFrames);
uint32 streamGetSize(void);
};
struct Clump : PluginBase<Clump>, Object
{
int32 numAtomics;
Atomic **atomicList;
int32 numLights;
Light **lightList;
int32 numCameras;
// cameras not implemented
Clump(void);
Clump(Clump *c);
~Clump(void);
static Clump *streamRead(std::istream &stream);
bool streamWrite(std::ostream &stream);
uint32 streamGetSize(void);
private:
void frameListStreamRead(std::istream &stream, Frame ***flp, int32 *nf);
void frameListStreamWrite(std::ostream &stream, Frame **flp, int32 nf);
};
}
void registerNodeNamePlugin(void);
void registerMeshPlugin(void);
void registerNativeDataPlugin(void);

27
src/rwogl.h Normal file
View File

@@ -0,0 +1,27 @@
namespace Rw {
struct OGLAttrib
{
// arguments to glVertexAttribPointer (should use OpenGL types here)
uint32 index;
int32 type;
bool32 normalized;
int32 size;
uint32 stride;
uint32 offset;
};
struct OGLInstanceDataHeader : InstanceDataHeader
{
int32 numAttribs;
OGLAttrib *attribs;
uint32 dataSize;
uint8 *data;
};
void *DestroyNativeDataOGL(void *object, int32, int32);
void ReadNativeDataOGL(std::istream &stream, int32 len, void *object, int32, int32);
void WriteNativeDataOGL(std::ostream &stream, int32 len, void *object, int32, int32);
int32 GetSizeNativeDataOGL(void *object, int32, int32);
}

186
src/rwplugin.h Normal file
View File

@@ -0,0 +1,186 @@
namespace Rw {
#define PLUGINOFFSET(type, base, offset) \
((type*)((char*)(base) + (offset)))
typedef void *(*Constructor)(void *object, int32 offset, int32 size);
typedef void *(*Destructor)(void *object, int32 offset, int32 size);
typedef void *(*CopyConstructor)(void *dst, void *src, int32 offset, int32 size);
typedef void (*StreamRead)(std::istream &stream, int32 length, void *object, int32 offset, int32 size);
typedef void (*StreamWrite)(std::ostream &stream, int32 length, void *object, int32 offset, int32 size);
typedef int32 (*StreamGetSize)(void *object, int32 offset, int32 size);
struct Plugin
{
int offset;
int size;
uint id;
Constructor constructor;
Destructor destructor;
CopyConstructor copy;
StreamRead read;
StreamWrite write;
StreamGetSize getSize;
Plugin *next;
};
template <typename T>
struct PluginBase
{
static int s_defaultSize;
static int s_size;
static Plugin *s_plugins;
void constructPlugins(void);
void destructPlugins(void);
void copyPlugins(T *t);
void streamReadPlugins(std::istream &stream);
void streamWritePlugins(std::ostream &stream);
int streamGetPluginSize(void);
static int registerPlugin(int size, uint id,
Constructor, Destructor, CopyConstructor);
static int registerPluginStream(uint id,
StreamRead, StreamWrite, StreamGetSize);
static int getPluginOffset(uint id);
static void *operator new(size_t size);
static void operator delete(void *p);
};
template <typename T>
int PluginBase<T>::s_defaultSize = sizeof(T);
template <typename T>
int PluginBase<T>::s_size = sizeof(T);
template <typename T>
Plugin *PluginBase<T>::s_plugins = 0;
template <typename T> void
PluginBase<T>::constructPlugins(void)
{
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->constructor)
p->constructor((void*)this, p->offset, p->size);
}
template <typename T> void
PluginBase<T>::destructPlugins(void)
{
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->destructor)
p->destructor((void*)this, p->offset, p->size);
}
template <typename T> void
PluginBase<T>::copyPlugins(T *t)
{
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->copy)
p->copy((void*)this, (void*)t, p->offset, p->size);
}
template <typename T> void
PluginBase<T>::streamReadPlugins(std::istream &stream)
{
uint32 length;
Rw::ChunkHeaderInfo header;
if(!Rw::FindChunk(stream, Rw::ID_EXTENSION, &length, NULL))
return;
while(length){
Rw::ReadChunkHeaderInfo(stream, &header);
length -= 12;
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->id == header.type){
p->read(stream, header.length,
(void*)this, p->offset, p->size);
goto cont;
}
stream.seekg(header.length, std::ios::cur);
cont:
length -= header.length;
}
}
template <typename T> void
PluginBase<T>::streamWritePlugins(std::ostream &stream)
{
int size = this->streamGetPluginSize();
Rw::WriteChunkHeader(stream, Rw::ID_EXTENSION, size);
for(Plugin *p = this->s_plugins; p; p = p->next){
if((size = p->getSize(this, p->offset, p->size)) < 0)
continue;
Rw::WriteChunkHeader(stream, p->id, size);
p->write(stream, size, this, p->offset, p->size);
}
}
template <typename T> int
PluginBase<T>::streamGetPluginSize(void)
{
int size = 0;
int plgsize;
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->getSize &&
(plgsize = p->getSize(this, p->offset, p->size)) >= 0)
size += 12 + plgsize;
return size;
}
template <typename T> int
PluginBase<T>::registerPlugin(int size, uint id,
Constructor ctor, Destructor dtor, CopyConstructor cctor)
{
Plugin *p = new Plugin;
p->offset = s_size;
s_size += size;
p->size = size;
p->id = id;
p->constructor = ctor;
p->copy = cctor;
p->destructor = dtor;
p->read = NULL;
p->write = NULL;
p->getSize = NULL;
p->next = s_plugins;
s_plugins = p;
return p->offset;
}
template <typename T> int
PluginBase<T>::registerPluginStream(uint id,
StreamRead read, StreamWrite write, StreamGetSize getSize)
{
for(Plugin *p = PluginBase<T>::s_plugins; p; p = p->next)
if(p->id == id){
p->read = read;
p->write = write;
p->getSize = getSize;
return p->offset;
}
return -1;
}
template <typename T> int
PluginBase<T>::getPluginOffset(uint id)
{
for(Plugin *p = PluginBase<T>::s_plugins; p; p = p->next)
if(p->id == id)
return p->offset;
return -1;
}
template <typename T> void*
PluginBase<T>::operator new(size_t)
{
void *m = malloc(T::s_size);
if(!m)
throw std::bad_alloc();
return m;
}
template <typename T> void
PluginBase<T>::operator delete(void *p)
{
free(p);
}
}

22
src/rwps2.h Normal file
View File

@@ -0,0 +1,22 @@
namespace Rw {
struct PS2InstanceData
{
uint32 noRefChain;
uint32 dataSize;
uint8 *data;
Material *material;
};
struct PS2InstanceDataHeader : InstanceDataHeader
{
uint32 numMeshes;
PS2InstanceData *instanceMeshes;
};
void *DestroyNativeDataPS2(void *object, int32, int32);
void ReadNativeDataPS2(std::istream &stream, int32 len, void *object, int32, int32);
void WriteNativeDataPS2(std::ostream &stream, int32 len, void *object, int32, int32);
int32 GetSizeNativeDataPS2(void *object, int32, int32);
}