implemented basic error system; restructured some files; replaced a few asserts

This commit is contained in:
aap 2016-06-17 00:06:37 +02:00
parent 416ee91bb7
commit 6e71e34933
14 changed files with 857 additions and 574 deletions

1
rw.h
View File

@ -2,6 +2,7 @@
#include <cmath>
#include "src/rwbase.h"
#include "src/rwerror.h"
#include "src/rwplg.h"
#include "src/rwpipeline.h"
#include "src/rwobjects.h"

8
src/base.err Normal file
View File

@ -0,0 +1,8 @@
ECODE(ERR_GENERAL,
"General Error")
ECODE(ERR_ALLOC,
"Couldn't allocate 0x%X bytes")
ECODE(ERR_FILE,
"Couldn't open file %s")
ECODE(ERR_CHUNK,
"Couldn't find chunk %s")

167
src/camera.cpp Normal file
View File

@ -0,0 +1,167 @@
#include <cstdio>
#include <cstdlib>
#include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#define PLUGIN_ID 0
namespace rw {
Camera*
Camera::create(void)
{
Camera *cam = (Camera*)malloc(PluginBase::s_size);
if(cam == NULL){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return NULL;
}
cam->object.object.init(Camera::ID, 0);
cam->viewWindow.set(1.0f, 1.0f);
cam->viewOffset.set(0.0f, 0.0f);
cam->nearPlane = 0.05f;
cam->farPlane = 10.0f;
cam->fogPlane = 5.0f;
cam->projection = Camera::PERSPECTIVE;
cam->clump = NULL;
cam->inClump.init();
cam->constructPlugins();
return cam;
}
Camera*
Camera::clone(void)
{
Camera *cam = Camera::create();
if(cam == NULL)
return NULL;
cam->object.object.copy(&this->object.object);
cam->setFrame(this->getFrame());
cam->viewWindow = this->viewWindow;
cam->viewOffset = this->viewOffset;
cam->nearPlane = this->nearPlane;
cam->farPlane = this->farPlane;
cam->fogPlane = this->fogPlane;
cam->projection = this->projection;
cam->copyPlugins(this);
return cam;
}
void
Camera::destroy(void)
{
this->destructPlugins();
if(this->clump)
this->inClump.remove();
free(this);
}
struct CameraChunkData
{
V2d viewWindow;
V2d viewOffset;
float32 nearPlane, farPlane;
float32 fogPlane;
int32 projection;
};
Camera*
Camera::streamRead(Stream *stream)
{
CameraChunkData buf;
if(!findChunk(stream, ID_STRUCT, NULL, NULL)){
RWERROR((ERR_CHUNK, "STRUCT"));
return NULL;
}
stream->read(&buf, sizeof(CameraChunkData));
Camera *cam = Camera::create();
cam->viewWindow = buf.viewWindow;
cam->viewOffset = buf.viewOffset;
cam->nearPlane = buf.nearPlane;
cam->farPlane = buf.farPlane;
cam->fogPlane = buf.fogPlane;
cam->projection = buf.projection;
cam->streamReadPlugins(stream);
return cam;
}
bool
Camera::streamWrite(Stream *stream)
{
CameraChunkData buf;
writeChunkHeader(stream, ID_CAMERA, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, sizeof(CameraChunkData));
buf.viewWindow = this->viewWindow;
buf.viewOffset = this->viewOffset;
buf.nearPlane = this->nearPlane;
buf.farPlane = this->farPlane;
buf.fogPlane = this->fogPlane;
buf.projection = this->projection;
stream->write(&buf, sizeof(CameraChunkData));
this->streamWritePlugins(stream);
return true;
}
uint32
Camera::streamGetSize(void)
{
return 12 + sizeof(CameraChunkData) + 12 + this->streamGetPluginSize();
}
void
Camera::updateProjectionMatrix(void)
{
float32 invwx = 1.0f/this->viewWindow.x;
float32 invwy = 1.0f/this->viewWindow.y;
float32 invz = 1.0f/(this->farPlane-this->nearPlane);
if(rw::platform == PLATFORM_D3D8 || rw::platform == PLATFORM_D3D9 ||
rw::platform == PLATFORM_XBOX){
// is this all really correct?
this->projMat[0] = invwx;
this->projMat[1] = 0.0f;
this->projMat[2] = 0.0f;
this->projMat[3] = 0.0f;
this->projMat[4] = 0.0f;
this->projMat[5] = invwy;
this->projMat[6] = 0.0f;
this->projMat[7] = 0.0f;
if(this->projection == PERSPECTIVE){
this->projMat[8] = this->viewOffset.x*invwx;
this->projMat[9] = this->viewOffset.y*invwy;
this->projMat[10] = this->farPlane*invz;
this->projMat[11] = 1.0f;
this->projMat[12] = 0.0f;
this->projMat[13] = 0.0f;
this->projMat[14] = -this->nearPlane*this->projMat[10];
this->projMat[15] = 0.0f;
}else{
this->projMat[8] = 0.0f;
this->projMat[9] = 0.0f;
this->projMat[10] = invz;
this->projMat[11] = 0.0f;
this->projMat[12] = this->viewOffset.x*invwx;
this->projMat[13] = this->viewOffset.y*invwy;
this->projMat[14] = -this->nearPlane*this->projMat[10];
this->projMat[15] = 1.0f;
}
}
}
void
Camera::setFOV(float32 fov, float32 ratio)
{
float32 a = tan(fov*3.14159f/360.0f);
this->viewWindow.x = a;
this->viewWindow.y = a/ratio;
this->viewOffset.set(0.0f, 0.0f);
}
}

View File

@ -1,267 +1,19 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cmath>
#include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#include "rwengine.h"
#include "rwps2.h"
#include "rwxbox.h"
#include "rwd3d8.h"
#include "rwd3d9.h"
#include "rwwdgl.h"
using namespace std;
#define PLUGIN_ID 2
namespace rw {
LinkList Frame::dirtyList;
Frame*
Frame::create(void)
{
Frame *f = (Frame*)malloc(PluginBase::s_size);
assert(f != NULL);
f->object.init(Frame::ID, 0);
f->objectList.init();
f->child = NULL;
f->next = NULL;
f->root = f;
f->matrix.setIdentity();
f->ltm.setIdentity();
f->constructPlugins();
return f;
}
Frame*
Frame::cloneHierarchy(void)
{
Frame *frame = this->cloneAndLink(NULL);
frame->purgeClone();
return frame;
}
void
Frame::destroy(void)
{
this->destructPlugins();
Frame *parent = this->getParent();
Frame *child;
if(parent){
// remove from child list
child = parent->child;
if(child == this)
parent->child = this->next;
else{
for(child = child->next; child != this; child = child->next)
;
child->next = this->next;
}
this->object.parent = NULL;
// Doesn't seem to make much sense, blame criterion.
this->setHierarchyRoot(this);
}
for(Frame *f = this->child; f; f = f->next)
f->object.parent = NULL;
free(this);
}
void
Frame::destroyHierarchy(void)
{
Frame *next;
for(Frame *child = this->child; child; child = next){
next = child->next;
child->destroyHierarchy();
}
this->destructPlugins();
free(this);
}
Frame*
Frame::addChild(Frame *child, bool32 append)
{
Frame *c;
if(child->getParent())
child->removeChild();
if(append){
if(this->child == NULL)
this->child = child;
else{
for(c = this->child; c->next; c = c->next);
c->next = child;
}
child->next = NULL;
}else{
child->next = this->child;
this->child = child;
}
child->object.parent = this;
child->root = this->root;
for(c = child->child; c; c = c->next)
c->setHierarchyRoot(this);
if(child->object.privateFlags & Frame::HIERARCHYSYNC){
child->inDirtyList.remove();
child->object.privateFlags &= ~Frame::HIERARCHYSYNC;
}
this->updateObjects();
return this;
}
Frame*
Frame::removeChild(void)
{
Frame *parent = this->getParent();
Frame *child = parent->child;
if(child == this)
parent->child = this->next;
else{
while(child->next != this)
child = child->next;
child->next = this->next;
}
this->object.parent = this->next = NULL;
this->root = this;
for(child = this->child; child; child = child->next)
child->setHierarchyRoot(this);
this->updateObjects();
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 void
syncRecurse(Frame *frame, uint8 flags)
{
uint8 flg;
for(; frame; frame = frame->next){
flg = flags | frame->object.privateFlags;
if(flg & Frame::SUBTREESYNCLTM){
Matrix::mult(&frame->ltm, &frame->getParent()->ltm, &frame->matrix);
frame->object.privateFlags &= ~Frame::SUBTREESYNCLTM;
}
syncRecurse(frame->child, flg);
}
}
void
Frame::syncHierarchyLTM(void)
{
Frame *child;
uint8 flg;
if(this->object.privateFlags & Frame::SUBTREESYNCLTM)
this->ltm = this->matrix;
for(child = this->child; child; child = child->next){
flg = this->object.privateFlags | child->object.privateFlags;
if(flg & Frame::SUBTREESYNCLTM){
Matrix::mult(&child->ltm, &this->ltm, &child->matrix);
child->object.privateFlags &= ~Frame::SUBTREESYNCLTM;
}
syncRecurse(child, flg);
}
this->object.privateFlags &= ~Frame::SYNCLTM;
}
Matrix*
Frame::getLTM(void)
{
if(this->root->object.privateFlags & Frame::HIERARCHYSYNCLTM)
this->root->syncHierarchyLTM();
return &this->ltm;
}
void
Frame::updateObjects(void)
{
if((this->root->object.privateFlags & HIERARCHYSYNC) == 0)
Frame::dirtyList.add(&this->inDirtyList);
this->root->object.privateFlags |= HIERARCHYSYNC;
this->object.privateFlags |= SUBTREESYNC;
}
void
Frame::setHierarchyRoot(Frame *root)
{
this->root = root;
for(Frame *child = this->child; child; child = child->next)
child->setHierarchyRoot(root);
}
// Clone a frame hierarchy. Link cloned frames into Frame::root of the originals.
Frame*
Frame::cloneAndLink(Frame *clonedroot)
{
Frame *frame = Frame::create();
if(clonedroot == NULL)
clonedroot = frame;
frame->object.copy(&this->object);
frame->matrix = this->matrix;
//memcpy(frame->matrix, this->matrix, sizeof(this->matrix));
frame->root = clonedroot;
this->root = frame; // Remember cloned frame
for(Frame *child = this->child; child; child = child->next){
Frame *clonedchild = child->cloneAndLink(clonedroot);
clonedchild->next = frame->child;
frame->child = clonedchild;
clonedchild->object.parent = frame;
}
frame->copyPlugins(this);
return frame;
}
// Remove links to cloned frames from hierarchy.
void
Frame::purgeClone(void)
{
Frame *parent = this->getParent();
this->setHierarchyRoot(parent ? parent->root : this);
}
static Frame*
sizeCB(Frame *f, void *size)
{
*(int32*)size += f->streamGetPluginSize();
f->forAllChildren(sizeCB, size);
return f;
}
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
//
@ -270,7 +22,10 @@ Clump*
Clump::create(void)
{
Clump *clump = (Clump*)malloc(PluginBase::s_size);
assert(clump != NULL);
if(clump == nil){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return nil;
}
clump->object.init(Clump::ID, 0);
clump->atomics.init();
clump->lights.init();
@ -318,8 +73,14 @@ Clump::streamRead(Stream *stream)
uint32 length, version;
int32 buf[3];
Clump *clump;
assert(findChunk(stream, ID_STRUCT, &length, &version));
if(!findChunk(stream, ID_STRUCT, &length, &version)){
RWERROR((ERR_CHUNK, "STRUCT"));
return nil;
}
clump = Clump::create();
if(clump == nil)
return nil;
stream->read(buf, length);
int32 numAtomics = buf[0];
int32 numLights = 0;
@ -339,31 +100,68 @@ Clump::streamRead(Stream *stream)
if(version >= 0x30400){
// Geometry list
int32 numGeometries = 0;
assert(findChunk(stream, ID_GEOMETRYLIST, NULL, NULL));
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
if(!findChunk(stream, ID_GEOMETRYLIST, nil, nil)){
RWERROR((ERR_CHUNK, "GEOMETRYLIST"));
// TODO: free
return nil;
}
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
// TODO: free
return nil;
}
numGeometries = stream->readI32();
if(numGeometries)
geometryList = new Geometry*[numGeometries];
for(int32 i = 0; i < numGeometries; i++){
assert(findChunk(stream, ID_GEOMETRY, NULL, NULL));
if(!findChunk(stream, ID_GEOMETRY, nil, nil)){
RWERROR((ERR_CHUNK, "GEOMETRY"));
// TODO: free
return nil;
}
geometryList[i] = Geometry::streamRead(stream);
if(geometryList[i] == nil){
// TODO: free
return nil;
}
}
}
// Atomics
Atomic *a;
for(int32 i = 0; i < numAtomics; i++){
assert(findChunk(stream, ID_ATOMIC, NULL, NULL));
Atomic *a = Atomic::streamReadClump(stream, frameList, geometryList);
if(!findChunk(stream, ID_ATOMIC, nil, nil)){
RWERROR((ERR_CHUNK, "ATOMIC"));
// TODO: free
return nil;
}
a = Atomic::streamReadClump(stream, frameList, geometryList);
if(a == nil){
// TODO: free
return nil;
}
clump->addAtomic(a);
}
// Lights
for(int32 i = 0; i < numLights; i++){
int32 frm;
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
// TODO: free
return nil;
}
frm = stream->readI32();
assert(findChunk(stream, ID_LIGHT, NULL, NULL));
if(!findChunk(stream, ID_LIGHT, nil, nil)){
RWERROR((ERR_CHUNK, "LIGHT"));
// TODO: free
return nil;
}
Light *l = Light::streamRead(stream);
if(l == nil){
// TODO: free
return nil;
}
l->setFrame(frameList[frm]);
clump->addLight(l);
}
@ -371,10 +169,22 @@ Clump::streamRead(Stream *stream)
// Cameras
for(int32 i = 0; i < numCameras; i++){
int32 frm;
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
// TODO: free
return nil;
}
frm = stream->readI32();
assert(findChunk(stream, ID_CAMERA, NULL, NULL));
if(!findChunk(stream, ID_CAMERA, nil, nil)){
RWERROR((ERR_CHUNK, "CAMERA"));
// TODO: free
return nil;
}
Camera *cam = Camera::streamRead(stream);
if(cam == nil){
// TODO: free
return nil;
}
cam->setFrame(frameList[frm]);
clump->addCamera(cam);
}
@ -450,6 +260,14 @@ struct FrameStreamData
int32 matflag;
};
static Frame*
sizeCB(Frame *f, void *size)
{
*(int32*)size += f->streamGetPluginSize();
f->forAllChildren(sizeCB, size);
return f;
}
uint32
Clump::streamGetSize(void)
{
@ -498,13 +316,19 @@ Clump::render(void)
}
}
void
bool
Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf)
{
FrameStreamData buf;
int32 numFrames = 0;
assert(findChunk(stream, ID_FRAMELIST, NULL, NULL));
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
if(!findChunk(stream, ID_FRAMELIST, nil, nil)){
RWERROR((ERR_CHUNK, "FRAMELIST"));
return 0;
}
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
return 0;
}
numFrames = stream->readI32();
Frame **frameList = new Frame*[numFrames];
for(int32 i = 0; i < numFrames; i++){
@ -527,6 +351,7 @@ Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf)
frameList[i]->streamReadPlugins(stream);
*nf = numFrames;
*flp = frameList;
return 1;
}
void
@ -566,14 +391,17 @@ Atomic*
Atomic::create(void)
{
Atomic *atomic = (Atomic*)malloc(PluginBase::s_size);
assert(atomic != NULL);
if(atomic == nil){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return nil;
}
atomic->object.object.init(Atomic::ID, 0);
atomic->geometry = NULL;
atomic->geometry = nil;
atomic->worldBoundingSphere.center.set(0.0f, 0.0f, 0.0f);
atomic->worldBoundingSphere.radius = 0.0f;
atomic->setFrame(NULL);
atomic->clump = NULL;
atomic->pipeline = NULL;
atomic->setFrame(nil);
atomic->clump = nil;
atomic->pipeline = nil;
atomic->renderCB = Atomic::defaultRenderCB;
atomic->object.object.flags = Atomic::COLLISIONTEST | Atomic::RENDER;
atomic->constructPlugins();
@ -603,7 +431,7 @@ Atomic::destroy(void)
this->geometry->destroy();
if(this->clump)
this->inClump.remove();
this->setFrame(NULL);
this->setFrame(nil);
free(this);
}
@ -612,7 +440,7 @@ Atomic::removeFromClump(void)
{
if(this->clump){
this->inClump.remove();
this->clump = NULL;
this->clump = nil;
}
}
@ -640,13 +468,26 @@ Atomic::streamReadClump(Stream *stream,
{
int32 buf[4];
uint32 version;
assert(findChunk(stream, ID_STRUCT, NULL, &version));
if(!findChunk(stream, ID_STRUCT, nil, &version)){
RWERROR((ERR_CHUNK, "STRUCT"));
return nil;
}
stream->read(buf, version < 0x30400 ? 12 : 16);
Atomic *atomic = Atomic::create();
if(atomic == nil)
return nil;
atomic->setFrame(frameList[buf[0]]);
if(version < 0x30400){
assert(findChunk(stream, ID_GEOMETRY, NULL, NULL));
if(!findChunk(stream, ID_GEOMETRY, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
// TODO: free
return nil;
}
atomic->geometry = Geometry::streamRead(stream);
if(atomic->geometry == nil){
// TODO: free
return nil;
}
}else
atomic->geometry = geometryList[buf[1]];
atomic->object.object.flags = buf[2];
@ -663,7 +504,7 @@ Atomic::streamWriteClump(Stream *stream, Frame **frameList, int32 numFrames)
{
int32 buf[4] = { 0, 0, 0, 0 };
Clump *c = this->clump;
if(c == NULL)
if(c == nil)
return false;
writeChunkHeader(stream, ID_ATOMIC, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, rw::version < 0x30400 ? 12 : 16);
@ -737,7 +578,7 @@ static int32
getSizeAtomicRights(void *object, int32, int32)
{
Atomic *atomic = (Atomic*)object;
if(atomic->pipeline == NULL || atomic->pipeline->pluginID == 0)
if(atomic->pipeline == nil || atomic->pipeline->pluginID == 0)
return -1;
return 8;
}
@ -745,272 +586,11 @@ getSizeAtomicRights(void *object, int32, int32)
void
registerAtomicRightsPlugin(void)
{
Atomic::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL);
Atomic::registerPlugin(0, ID_RIGHTTORENDER, nil, nil, nil);
Atomic::registerPluginStream(ID_RIGHTTORENDER,
readAtomicRights,
writeAtomicRights,
getSizeAtomicRights);
}
//
// Light
//
Light*
Light::create(int32 type)
{
Light *light = (Light*)malloc(PluginBase::s_size);
assert(light != NULL);
light->object.object.init(Light::ID, type);
light->radius = 0.0f;
light->color.red = 1.0f;
light->color.green = 1.0f;
light->color.blue = 1.0f;
light->color.alpha = 1.0f;
light->minusCosAngle = 1.0f;
light->object.object.privateFlags = 1;
light->object.object.flags = LIGHTATOMICS | LIGHTWORLD;
light->clump = NULL;
light->inClump.init();
light->constructPlugins();
return light;
}
void
Light::destroy(void)
{
this->destructPlugins();
if(this->clump)
this->inClump.remove();
free(this);
}
void
Light::setAngle(float32 angle)
{
this->minusCosAngle = -cos(angle);
}
float32
Light::getAngle(void)
{
return acos(-this->minusCosAngle);
}
void
Light::setColor(float32 r, float32 g, float32 b)
{
this->color.red = r;
this->color.green = g;
this->color.blue = b;
this->object.object.privateFlags = r == g && r == b;
}
struct LightChunkData
{
float32 radius;
float32 red, green, blue;
float32 minusCosAngle;
uint16 flags;
uint16 type;
};
Light*
Light::streamRead(Stream *stream)
{
uint32 version;
LightChunkData buf;
assert(findChunk(stream, ID_STRUCT, NULL, &version));
stream->read(&buf, sizeof(LightChunkData));
Light *light = Light::create(buf.type);
light->radius = buf.radius;
light->setColor(buf.red, buf.green, buf.blue);
float32 a = buf.minusCosAngle;
if(version >= 0x30300)
light->minusCosAngle = a;
else
// tan -> -cos
light->minusCosAngle = -1.0f/sqrt(a*a+1.0f);
light->object.object.flags = (uint8)buf.flags;
light->streamReadPlugins(stream);
return light;
}
bool
Light::streamWrite(Stream *stream)
{
LightChunkData buf;
writeChunkHeader(stream, ID_LIGHT, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, sizeof(LightChunkData));
buf.radius = this->radius;
buf.red = this->color.red;
buf.green = this->color.green;
buf.blue = this->color.blue;
if(version >= 0x30300)
buf.minusCosAngle = this->minusCosAngle;
else
buf.minusCosAngle = tan(acos(-this->minusCosAngle));
buf.flags = this->object.object.flags;
buf.type = this->object.object.subType;
stream->write(&buf, sizeof(LightChunkData));
this->streamWritePlugins(stream);
return true;
}
uint32
Light::streamGetSize(void)
{
return 12 + sizeof(LightChunkData) + 12 + this->streamGetPluginSize();
}
//
// Camera
//
Camera*
Camera::create(void)
{
Camera *cam = (Camera*)malloc(PluginBase::s_size);
cam->object.object.init(Camera::ID, 0);
cam->viewWindow.set(1.0f, 1.0f);
cam->viewOffset.set(0.0f, 0.0f);
cam->nearPlane = 0.05f;
cam->farPlane = 10.0f;
cam->fogPlane = 5.0f;
cam->projection = Camera::PERSPECTIVE;
cam->clump = NULL;
cam->inClump.init();
cam->constructPlugins();
return cam;
}
Camera*
Camera::clone(void)
{
Camera *cam = Camera::create();
cam->object.object.copy(&this->object.object);
cam->setFrame(this->getFrame());
cam->viewWindow = this->viewWindow;
cam->viewOffset = this->viewOffset;
cam->nearPlane = this->nearPlane;
cam->farPlane = this->farPlane;
cam->fogPlane = this->fogPlane;
cam->projection = this->projection;
cam->copyPlugins(this);
return cam;
}
void
Camera::destroy(void)
{
this->destructPlugins();
if(this->clump)
this->inClump.remove();
free(this);
}
struct CameraChunkData
{
V2d viewWindow;
V2d viewOffset;
float32 nearPlane, farPlane;
float32 fogPlane;
int32 projection;
};
Camera*
Camera::streamRead(Stream *stream)
{
CameraChunkData buf;
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
stream->read(&buf, sizeof(CameraChunkData));
Camera *cam = Camera::create();
cam->viewWindow = buf.viewWindow;
cam->viewOffset = buf.viewOffset;
cam->nearPlane = buf.nearPlane;
cam->farPlane = buf.farPlane;
cam->fogPlane = buf.fogPlane;
cam->projection = buf.projection;
cam->streamReadPlugins(stream);
return cam;
}
bool
Camera::streamWrite(Stream *stream)
{
CameraChunkData buf;
writeChunkHeader(stream, ID_CAMERA, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, sizeof(CameraChunkData));
buf.viewWindow = this->viewWindow;
buf.viewOffset = this->viewOffset;
buf.nearPlane = this->nearPlane;
buf.farPlane = this->farPlane;
buf.fogPlane = this->fogPlane;
buf.projection = this->projection;
stream->write(&buf, sizeof(CameraChunkData));
this->streamWritePlugins(stream);
return true;
}
uint32
Camera::streamGetSize(void)
{
return 12 + sizeof(CameraChunkData) + 12 + this->streamGetPluginSize();
}
void
Camera::updateProjectionMatrix(void)
{
float32 invwx = 1.0f/this->viewWindow.x;
float32 invwy = 1.0f/this->viewWindow.y;
float32 invz = 1.0f/(this->farPlane-this->nearPlane);
if(rw::platform == PLATFORM_D3D8 || rw::platform == PLATFORM_D3D9 ||
rw::platform == PLATFORM_XBOX){
// is this all really correct?
this->projMat[0] = invwx;
this->projMat[1] = 0.0f;
this->projMat[2] = 0.0f;
this->projMat[3] = 0.0f;
this->projMat[4] = 0.0f;
this->projMat[5] = invwy;
this->projMat[6] = 0.0f;
this->projMat[7] = 0.0f;
if(this->projection == PERSPECTIVE){
this->projMat[8] = this->viewOffset.x*invwx;
this->projMat[9] = this->viewOffset.y*invwy;
this->projMat[10] = this->farPlane*invz;
this->projMat[11] = 1.0f;
this->projMat[12] = 0.0f;
this->projMat[13] = 0.0f;
this->projMat[14] = -this->nearPlane*this->projMat[10];
this->projMat[15] = 0.0f;
}else{
this->projMat[8] = 0.0f;
this->projMat[9] = 0.0f;
this->projMat[10] = invz;
this->projMat[11] = 0.0f;
this->projMat[12] = this->viewOffset.x*invwx;
this->projMat[13] = this->viewOffset.y*invwy;
this->projMat[14] = -this->nearPlane*this->projMat[10];
this->projMat[15] = 1.0f;
}
}
}
void
Camera::setFOV(float32 fov, float32 ratio)
{
float32 a = tan(fov*3.14159f/360.0f);
this->viewWindow.x = a;
this->viewWindow.y = a/ratio;
this->viewOffset.set(0.0f, 0.0f);
}
}

View File

@ -1,5 +1,6 @@
#include <cstdio>
#include <assert.h>
#include <cstdlib>
#include <cassert>
#include "rwbase.h"
#include "rwplg.h"

49
src/error.cpp Normal file
View File

@ -0,0 +1,49 @@
#include <cstdio>
#include <stdarg.h>
#include "rwbase.h"
#include "rwerror.h"
namespace rw {
static Error error;
void
setError(Error *e)
{
error = *e;
}
Error*
getError(Error *e)
{
*e = error;
error.plugin = 0;
error.code = 0;
return e;
}
#define ECODE(c, s) s,
const char *errstrs[] = {
"No error",
#include "base.err"
};
#undef ECODE
char*
dbgsprint(int32 code, ...)
{
va_list ap;
static char strbuf[512];
if(code & 0x80000000)
code &= ~0x80000000;
va_start(ap, code);
vsprintf(strbuf, errstrs[code], ap);
va_end(ap);
return strbuf;
}
}

262
src/frame.cpp Normal file
View File

@ -0,0 +1,262 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cmath>
#include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#include "rwengine.h"
#include "rwps2.h"
#include "rwxbox.h"
#include "rwd3d8.h"
#include "rwd3d9.h"
#include "rwwdgl.h"
#define PLUGIN_ID 0
namespace rw {
LinkList Frame::dirtyList;
Frame*
Frame::create(void)
{
Frame *f = (Frame*)malloc(PluginBase::s_size);
if(f == NULL){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return NULL;
}
f->object.init(Frame::ID, 0);
f->objectList.init();
f->child = NULL;
f->next = NULL;
f->root = f;
f->matrix.setIdentity();
f->ltm.setIdentity();
f->constructPlugins();
return f;
}
Frame*
Frame::cloneHierarchy(void)
{
Frame *frame = this->cloneAndLink(NULL);
frame->purgeClone();
return frame;
}
void
Frame::destroy(void)
{
this->destructPlugins();
Frame *parent = this->getParent();
Frame *child;
if(parent){
// remove from child list
child = parent->child;
if(child == this)
parent->child = this->next;
else{
for(child = child->next; child != this; child = child->next)
;
child->next = this->next;
}
this->object.parent = NULL;
// Doesn't seem to make much sense, blame criterion.
this->setHierarchyRoot(this);
}
for(Frame *f = this->child; f; f = f->next)
f->object.parent = NULL;
free(this);
}
void
Frame::destroyHierarchy(void)
{
Frame *next;
for(Frame *child = this->child; child; child = next){
next = child->next;
child->destroyHierarchy();
}
this->destructPlugins();
free(this);
}
Frame*
Frame::addChild(Frame *child, bool32 append)
{
Frame *c;
if(child->getParent())
child->removeChild();
if(append){
if(this->child == NULL)
this->child = child;
else{
for(c = this->child; c->next; c = c->next);
c->next = child;
}
child->next = NULL;
}else{
child->next = this->child;
this->child = child;
}
child->object.parent = this;
child->root = this->root;
for(c = child->child; c; c = c->next)
c->setHierarchyRoot(this);
if(child->object.privateFlags & Frame::HIERARCHYSYNC){
child->inDirtyList.remove();
child->object.privateFlags &= ~Frame::HIERARCHYSYNC;
}
this->updateObjects();
return this;
}
Frame*
Frame::removeChild(void)
{
Frame *parent = this->getParent();
Frame *child = parent->child;
if(child == this)
parent->child = this->next;
else{
while(child->next != this)
child = child->next;
child->next = this->next;
}
this->object.parent = this->next = NULL;
this->root = this;
for(child = this->child; child; child = child->next)
child->setHierarchyRoot(this);
this->updateObjects();
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 void
syncRecurse(Frame *frame, uint8 flags)
{
uint8 flg;
for(; frame; frame = frame->next){
flg = flags | frame->object.privateFlags;
if(flg & Frame::SUBTREESYNCLTM){
Matrix::mult(&frame->ltm, &frame->getParent()->ltm,
&frame->matrix);
frame->object.privateFlags &= ~Frame::SUBTREESYNCLTM;
}
syncRecurse(frame->child, flg);
}
}
void
Frame::syncHierarchyLTM(void)
{
Frame *child;
uint8 flg;
if(this->object.privateFlags & Frame::SUBTREESYNCLTM)
this->ltm = this->matrix;
for(child = this->child; child; child = child->next){
flg = this->object.privateFlags | child->object.privateFlags;
if(flg & Frame::SUBTREESYNCLTM){
Matrix::mult(&child->ltm, &this->ltm, &child->matrix);
child->object.privateFlags &= ~Frame::SUBTREESYNCLTM;
}
syncRecurse(child, flg);
}
this->object.privateFlags &= ~Frame::SYNCLTM;
}
Matrix*
Frame::getLTM(void)
{
if(this->root->object.privateFlags & Frame::HIERARCHYSYNCLTM)
this->root->syncHierarchyLTM();
return &this->ltm;
}
void
Frame::updateObjects(void)
{
if((this->root->object.privateFlags & HIERARCHYSYNC) == 0)
Frame::dirtyList.add(&this->inDirtyList);
this->root->object.privateFlags |= HIERARCHYSYNC;
this->object.privateFlags |= SUBTREESYNC;
}
void
Frame::setHierarchyRoot(Frame *root)
{
this->root = root;
for(Frame *child = this->child; child; child = child->next)
child->setHierarchyRoot(root);
}
// Clone a frame hierarchy. Link cloned frames into Frame::root of the originals.
Frame*
Frame::cloneAndLink(Frame *clonedroot)
{
Frame *frame = Frame::create();
if(clonedroot == NULL)
clonedroot = frame;
frame->object.copy(&this->object);
frame->matrix = this->matrix;
//memcpy(frame->matrix, this->matrix, sizeof(this->matrix));
frame->root = clonedroot;
this->root = frame; // Remember cloned frame
for(Frame *child = this->child; child; child = child->next){
Frame *clonedchild = child->cloneAndLink(clonedroot);
clonedchild->next = frame->child;
frame->child = clonedchild;
clonedchild->object.parent = frame;
}
frame->copyPlugins(this);
return frame;
}
// Remove links to cloned frames from hierarchy.
void
Frame::purgeClone(void)
{
Frame *parent = this->getParent();
this->setHierarchyRoot(parent ? parent->root : this);
}
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;
}
}

View File

@ -5,10 +5,13 @@
#include <cmath>
#include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#define PLUGIN_ID 2
using namespace std;
namespace rw {
@ -17,7 +20,10 @@ Geometry*
Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
{
Geometry *geo = (Geometry*)malloc(PluginBase::s_size);
assert(geo != NULL);
if(geo == nil){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return nil;
}
geo->object.init(Geometry::ID, 0);
geo->geoflags = flags & 0xFF00FFFF;
geo->numTexCoordSets = (flags & 0xFF0000) >> 16;
@ -28,10 +34,10 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
geo->numVertices = numVerts;
geo->numMorphTargets = 1;
geo->colors = NULL;
geo->colors = nil;
for(int32 i = 0; i < geo->numTexCoordSets; i++)
geo->texCoords[i] = NULL;
geo->triangles = NULL;
geo->texCoords[i] = nil;
geo->triangles = nil;
if(!(geo->geoflags & NATIVE) && geo->numVertices){
if(geo->geoflags & PRELIT)
geo->colors = new uint8[4*geo->numVertices];
@ -45,24 +51,23 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
MorphTarget *m = geo->morphTargets;
m->boundingSphere.center.set(0.0f, 0.0f, 0.0f);
m->boundingSphere.radius = 0.0f;
m->vertices = NULL;
m->normals = NULL;
m->vertices = nil;
m->normals = nil;
if(!(geo->geoflags & NATIVE) && geo->numVertices){
m->vertices = new float32[3*geo->numVertices];
if(geo->geoflags & NORMALS)
m->normals = new float32[3*geo->numVertices];
}
geo->numMaterials = 0;
geo->materialList = NULL;
geo->meshHeader = NULL;
geo->instData = NULL;
geo->materialList = nil;
geo->meshHeader = nil;
geo->instData = nil;
geo->refCount = 1;
geo->constructPlugins();
return geo;
}
void
Geometry::destroy(void)
{
@ -101,10 +106,15 @@ Geometry::streamRead(Stream *stream)
{
uint32 version;
GeoStreamData buf;
assert(findChunk(stream, ID_STRUCT, NULL, &version));
if(!findChunk(stream, ID_STRUCT, nil, &version)){
RWERROR((ERR_CHUNK, "STRUCT"));
return nil;
}
stream->read(&buf, sizeof(buf));
Geometry *geo = Geometry::create(buf.numVertices,
buf.numTriangles, buf.flags);
if(geo == nil)
return nil;
geo->addMorphTargets(buf.numMorphTargets-1);
// skip surface properties
if(version < 0x34000)
@ -137,13 +147,25 @@ Geometry::streamRead(Stream *stream)
stream->read(m->normals, 3*geo->numVertices*4);
}
assert(findChunk(stream, ID_MATLIST, NULL, NULL));
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
if(!findChunk(stream, ID_MATLIST, nil, nil)){
RWERROR((ERR_CHUNK, "MATLIST"));
// TODO: free
return nil;
}
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
// TODO: free
return nil;
}
geo->numMaterials = stream->readI32();
geo->materialList = new Material*[geo->numMaterials];
stream->seek(geo->numMaterials*4); // unused (-1)
for(int32 i = 0; i < geo->numMaterials; i++){
assert(findChunk(stream, ID_MATERIAL, NULL, NULL));
if(!findChunk(stream, ID_MATERIAL, nil, nil)){
RWERROR((ERR_CHUNK, "MATERIAL"));
// TODO: free
return nil;
}
geo->materialList[i] = Material::streamRead(stream);
}
@ -217,8 +239,8 @@ Geometry::streamWrite(Stream *stream)
MorphTarget *m = &this->morphTargets[i];
stream->write(&m->boundingSphere, 4*4);
if(!(this->geoflags & NATIVE)){
stream->writeI32(m->vertices != NULL);
stream->writeI32(m->normals != NULL);
stream->writeI32(m->vertices != nil);
stream->writeI32(m->normals != nil);
if(m->vertices)
stream->write(m->vertices,
3*this->numVertices*4);
@ -270,8 +292,8 @@ Geometry::addMorphTargets(int32 n)
this->morphTargets = morphTargets;
for(int32 i = this->numMorphTargets; i < n; i++){
MorphTarget *m = &morphTargets[i];
m->vertices = NULL;
m->normals = NULL;
m->vertices = nil;
m->normals = nil;
if(!(this->geoflags & NATIVE)){
m->vertices = new float32[3*this->numVertices];
if(this->geoflags & NORMALS)
@ -344,7 +366,7 @@ void
Geometry::generateTriangles(int8 *adc)
{
MeshHeader *header = this->meshHeader;
assert(header != NULL);
assert(header != nil);
this->numTriangles = 0;
Mesh *m = header->mesh;
@ -452,7 +474,7 @@ Geometry::buildMeshes(void)
void
Geometry::removeUnusedMaterials(void)
{
if(this->meshHeader == NULL)
if(this->meshHeader == nil)
return;
MeshHeader *mh = this->meshHeader;
int32 *map = new int32[this->numMaterials];
@ -515,13 +537,16 @@ Material*
Material::create(void)
{
Material *mat = (Material*)malloc(PluginBase::s_size);
assert(mat != NULL);
mat->texture = NULL;
if(mat == nil){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return nil;
}
mat->texture = nil;
memset(&mat->color, 0xFF, 4);
mat->surfaceProps.ambient = 1.0f;
mat->surfaceProps.specular = 1.0f;
mat->surfaceProps.diffuse = 1.0f;
mat->pipeline = NULL;
mat->pipeline = nil;
mat->refCount = 1;
mat->constructPlugins();
return mat;
@ -531,6 +556,10 @@ Material*
Material::clone(void)
{
Material *mat = Material::create();
if(mat == nil){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return nil;
}
mat->color = this->color;
mat->surfaceProps = this->surfaceProps;
if(this->texture){
@ -570,9 +599,14 @@ Material::streamRead(Stream *stream)
uint32 length, version;
MatStreamData buf;
assert(findChunk(stream, ID_STRUCT, NULL, &version));
if(!findChunk(stream, ID_STRUCT, nil, &version)){
RWERROR((ERR_CHUNK, "STRUCT"));
return nil;
}
stream->read(&buf, sizeof(buf));
Material *mat = Material::create();
if(mat == nil)
return nil;
mat->color = buf.color;
if(version < 0x30400){
mat->surfaceProps.ambient = 1.0f;
@ -586,8 +620,16 @@ Material::streamRead(Stream *stream)
mat->surfaceProps.diffuse = surfaceProps[2];
}
if(buf.textured){
assert(findChunk(stream, ID_TEXTURE, &length, NULL));
if(!findChunk(stream, ID_TEXTURE, &length, nil)){
RWERROR((ERR_CHUNK, "TEXTURE"));
// TODO: free
return nil;
}
mat->texture = Texture::streamRead(stream);
if(mat->texture == nil){
// TODO: fre
return nil;
}
}
materialRights[0] = 0;
@ -609,7 +651,7 @@ Material::streamWrite(Stream *stream)
buf.color = this->color;
buf.flags = 0;
buf.unused = 0;
buf.textured = this->texture != NULL;
buf.textured = this->texture != nil;
stream->write(&buf, sizeof(buf));
if(rw::version >= 0x30400){
@ -663,7 +705,7 @@ static int32
getSizeMaterialRights(void *object, int32, int32)
{
Material *material = (Material*)object;
if(material->pipeline == NULL || material->pipeline->pluginID == 0)
if(material->pipeline == nil || material->pipeline->pluginID == 0)
return -1;
return 8;
}
@ -671,7 +713,7 @@ getSizeMaterialRights(void *object, int32, int32)
void
registerMaterialRightsPlugin(void)
{
Material::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL);
Material::registerPlugin(0, ID_RIGHTTORENDER, nil, nil, nil);
Material::registerPluginStream(ID_RIGHTTORENDER,
readMaterialRights,
writeMaterialRights,

131
src/light.cpp Normal file
View File

@ -0,0 +1,131 @@
#include <cstdio>
#include <cstdlib>
#include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#define PLUGIN_ID 2
namespace rw {
Light*
Light::create(int32 type)
{
Light *light = (Light*)malloc(PluginBase::s_size);
if(light == NULL){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return NULL;
}
light->object.object.init(Light::ID, type);
light->radius = 0.0f;
light->color.red = 1.0f;
light->color.green = 1.0f;
light->color.blue = 1.0f;
light->color.alpha = 1.0f;
light->minusCosAngle = 1.0f;
light->object.object.privateFlags = 1;
light->object.object.flags = LIGHTATOMICS | LIGHTWORLD;
light->clump = NULL;
light->inClump.init();
light->constructPlugins();
return light;
}
void
Light::destroy(void)
{
this->destructPlugins();
if(this->clump)
this->inClump.remove();
free(this);
}
void
Light::setAngle(float32 angle)
{
this->minusCosAngle = -cos(angle);
}
float32
Light::getAngle(void)
{
return acos(-this->minusCosAngle);
}
void
Light::setColor(float32 r, float32 g, float32 b)
{
this->color.red = r;
this->color.green = g;
this->color.blue = b;
this->object.object.privateFlags = r == g && r == b;
}
struct LightChunkData
{
float32 radius;
float32 red, green, blue;
float32 minusCosAngle;
uint16 flags;
uint16 type;
};
Light*
Light::streamRead(Stream *stream)
{
uint32 version;
LightChunkData buf;
if(!findChunk(stream, ID_STRUCT, NULL, &version)){
RWERROR((ERR_CHUNK, "STRUCT"));
return NULL;
}
stream->read(&buf, sizeof(LightChunkData));
Light *light = Light::create(buf.type);
if(light == NULL)
return NULL;
light->radius = buf.radius;
light->setColor(buf.red, buf.green, buf.blue);
float32 a = buf.minusCosAngle;
if(version >= 0x30300)
light->minusCosAngle = a;
else
// tan -> -cos
light->minusCosAngle = -1.0f/sqrt(a*a+1.0f);
light->object.object.flags = (uint8)buf.flags;
light->streamReadPlugins(stream);
return light;
}
bool
Light::streamWrite(Stream *stream)
{
LightChunkData buf;
writeChunkHeader(stream, ID_LIGHT, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, sizeof(LightChunkData));
buf.radius = this->radius;
buf.red = this->color.red;
buf.green = this->color.green;
buf.blue = this->color.blue;
if(version >= 0x30300)
buf.minusCosAngle = this->minusCosAngle;
else
buf.minusCosAngle = tan(acos(-this->minusCosAngle));
buf.flags = this->object.object.flags;
buf.type = this->object.object.subType;
stream->write(&buf, sizeof(LightChunkData));
this->streamWritePlugins(stream);
return true;
}
uint32
Light::streamGetSize(void)
{
return 12 + sizeof(LightChunkData) + 12 + this->streamGetPluginSize();
}
}

View File

@ -6,6 +6,7 @@
#include <cctype>
#include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h"
#include "rwpipeline.h"
#include "rwobjects.h"
@ -21,6 +22,8 @@ using namespace std;
namespace rw {
#define PLUGIN_ID 0
int32 version = 0x36003;
int32 build = 0xFFFF;
#ifdef RW_PS2
@ -665,7 +668,11 @@ StreamFile*
StreamFile::open(const char *path, const char *mode)
{
this->file = fopen(path, mode);
return this->file ? this : NULL;
if(this->file == NULL){
RWERROR((ERR_FILE, path));
return NULL;
}
return this;
}
void
@ -758,10 +765,8 @@ findPointer(void *p, void **list, int32 num)
int i;
for(i = 0; i < num; i++)
if(list[i] == p)
goto found;
return i;
return -1;
found:
return i;
}
uint8*

View File

@ -33,6 +33,8 @@ typedef int32 bool32;
typedef uint8 byte;
typedef uint32 uint;
#define nil NULL
#define nelem(A) (sizeof(A) / sizeof A[0])
struct RGBA
@ -284,6 +286,16 @@ enum PluginID
ID_VERTEXFMT = 0x511,
};
#define ECODE(c, s) c,
enum Errors
{
ERR_NONE = 0x80000000,
#include "base.err"
};
#undef ECODE
extern int version;
extern int build;
extern int platform;

25
src/rwerror.h Normal file
View File

@ -0,0 +1,25 @@
namespace rw {
struct Error
{
uint32 plugin;
uint32 code;
};
void setError(Error *e);
Error *getError(Error *e);
#define _ERRORCODE(code, ...) code
char *dbgsprint(int32 code, ...);
/* ecode is supposed to be in format "(errorcode, printf-arguments..)" */
#define RWERROR(ecode) do{ \
rw::Error _e; \
_e.plugin = PLUGIN_ID; \
_e.code = _ERRORCODE ecode; \
fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \
fprintf(stderr, "%s\n", rw::dbgsprint ecode); \
rw::setError(&_e); \
}while(0);
}

View File

@ -544,7 +544,7 @@ struct Clump : PluginBase<Clump>
uint32 streamGetSize(void);
void render(void);
void frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf);
bool frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf);
void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf);
};

View File

@ -205,13 +205,13 @@ PluginBase<T>::getPluginOffset(uint32 id)
template <typename T> void*
PluginBase<T>::operator new(size_t)
{
assert(0);
abort();
return NULL;
}
template <typename T> void
PluginBase<T>::operator delete(void *p)
{
assert(0);
abort();
}
}