mirror of
https://github.com/aap/librw.git
synced 2025-12-19 00:49:50 +00:00
Organized the project properly.
This commit is contained in:
493
src/clump.cpp
Normal file
493
src/clump.cpp
Normal 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
464
src/geometry.cpp
Normal 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
71
src/ogl.cpp
Normal 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
265
src/plugins.cpp
Normal 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
92
src/ps2.cpp
Normal 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
175
src/rwbase.cpp
Normal 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
111
src/rwbase.h
Normal 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
213
src/rwobjects.h
Normal 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
27
src/rwogl.h
Normal 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
186
src/rwplugin.h
Normal 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
22
src/rwps2.h
Normal 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);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user