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 <cmath>
#include "src/rwbase.h" #include "src/rwbase.h"
#include "src/rwerror.h"
#include "src/rwplg.h" #include "src/rwplg.h"
#include "src/rwpipeline.h" #include "src/rwpipeline.h"
#include "src/rwobjects.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 <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring>
#include <cassert>
#include <cmath>
#include "rwbase.h" #include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h" #include "rwplg.h"
#include "rwpipeline.h" #include "rwpipeline.h"
#include "rwobjects.h" #include "rwobjects.h"
#include "rwengine.h" #include "rwengine.h"
#include "rwps2.h"
#include "rwxbox.h"
#include "rwd3d8.h"
#include "rwd3d9.h"
#include "rwwdgl.h"
using namespace std; using namespace std;
#define PLUGIN_ID 2
namespace rw { 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 // Clump
// //
@ -270,7 +22,10 @@ Clump*
Clump::create(void) Clump::create(void)
{ {
Clump *clump = (Clump*)malloc(PluginBase::s_size); 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->object.init(Clump::ID, 0);
clump->atomics.init(); clump->atomics.init();
clump->lights.init(); clump->lights.init();
@ -318,8 +73,14 @@ Clump::streamRead(Stream *stream)
uint32 length, version; uint32 length, version;
int32 buf[3]; int32 buf[3];
Clump *clump; 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(); clump = Clump::create();
if(clump == nil)
return nil;
stream->read(buf, length); stream->read(buf, length);
int32 numAtomics = buf[0]; int32 numAtomics = buf[0];
int32 numLights = 0; int32 numLights = 0;
@ -339,31 +100,68 @@ Clump::streamRead(Stream *stream)
if(version >= 0x30400){ if(version >= 0x30400){
// Geometry list // Geometry list
int32 numGeometries = 0; int32 numGeometries = 0;
assert(findChunk(stream, ID_GEOMETRYLIST, NULL, NULL)); if(!findChunk(stream, ID_GEOMETRYLIST, nil, nil)){
assert(findChunk(stream, ID_STRUCT, NULL, NULL)); 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(); numGeometries = stream->readI32();
if(numGeometries) if(numGeometries)
geometryList = new Geometry*[numGeometries]; geometryList = new Geometry*[numGeometries];
for(int32 i = 0; i < numGeometries; i++){ 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); geometryList[i] = Geometry::streamRead(stream);
if(geometryList[i] == nil){
// TODO: free
return nil;
}
} }
} }
// Atomics // Atomics
Atomic *a;
for(int32 i = 0; i < numAtomics; i++){ for(int32 i = 0; i < numAtomics; i++){
assert(findChunk(stream, ID_ATOMIC, NULL, NULL)); if(!findChunk(stream, ID_ATOMIC, nil, nil)){
Atomic *a = Atomic::streamReadClump(stream, frameList, geometryList); RWERROR((ERR_CHUNK, "ATOMIC"));
// TODO: free
return nil;
}
a = Atomic::streamReadClump(stream, frameList, geometryList);
if(a == nil){
// TODO: free
return nil;
}
clump->addAtomic(a); clump->addAtomic(a);
} }
// Lights // Lights
for(int32 i = 0; i < numLights; i++){ for(int32 i = 0; i < numLights; i++){
int32 frm; 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(); 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); Light *l = Light::streamRead(stream);
if(l == nil){
// TODO: free
return nil;
}
l->setFrame(frameList[frm]); l->setFrame(frameList[frm]);
clump->addLight(l); clump->addLight(l);
} }
@ -371,10 +169,22 @@ Clump::streamRead(Stream *stream)
// Cameras // Cameras
for(int32 i = 0; i < numCameras; i++){ for(int32 i = 0; i < numCameras; i++){
int32 frm; 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(); 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); Camera *cam = Camera::streamRead(stream);
if(cam == nil){
// TODO: free
return nil;
}
cam->setFrame(frameList[frm]); cam->setFrame(frameList[frm]);
clump->addCamera(cam); clump->addCamera(cam);
} }
@ -450,6 +260,14 @@ struct FrameStreamData
int32 matflag; int32 matflag;
}; };
static Frame*
sizeCB(Frame *f, void *size)
{
*(int32*)size += f->streamGetPluginSize();
f->forAllChildren(sizeCB, size);
return f;
}
uint32 uint32
Clump::streamGetSize(void) Clump::streamGetSize(void)
{ {
@ -498,13 +316,19 @@ Clump::render(void)
} }
} }
void bool
Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf) Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf)
{ {
FrameStreamData buf; FrameStreamData buf;
int32 numFrames = 0; int32 numFrames = 0;
assert(findChunk(stream, ID_FRAMELIST, NULL, NULL)); if(!findChunk(stream, ID_FRAMELIST, nil, nil)){
assert(findChunk(stream, ID_STRUCT, NULL, NULL)); RWERROR((ERR_CHUNK, "FRAMELIST"));
return 0;
}
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
return 0;
}
numFrames = stream->readI32(); numFrames = stream->readI32();
Frame **frameList = new Frame*[numFrames]; Frame **frameList = new Frame*[numFrames];
for(int32 i = 0; i < numFrames; i++){ for(int32 i = 0; i < numFrames; i++){
@ -527,6 +351,7 @@ Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf)
frameList[i]->streamReadPlugins(stream); frameList[i]->streamReadPlugins(stream);
*nf = numFrames; *nf = numFrames;
*flp = frameList; *flp = frameList;
return 1;
} }
void void
@ -566,14 +391,17 @@ Atomic*
Atomic::create(void) Atomic::create(void)
{ {
Atomic *atomic = (Atomic*)malloc(PluginBase::s_size); 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->object.object.init(Atomic::ID, 0);
atomic->geometry = NULL; atomic->geometry = nil;
atomic->worldBoundingSphere.center.set(0.0f, 0.0f, 0.0f); atomic->worldBoundingSphere.center.set(0.0f, 0.0f, 0.0f);
atomic->worldBoundingSphere.radius = 0.0f; atomic->worldBoundingSphere.radius = 0.0f;
atomic->setFrame(NULL); atomic->setFrame(nil);
atomic->clump = NULL; atomic->clump = nil;
atomic->pipeline = NULL; atomic->pipeline = nil;
atomic->renderCB = Atomic::defaultRenderCB; atomic->renderCB = Atomic::defaultRenderCB;
atomic->object.object.flags = Atomic::COLLISIONTEST | Atomic::RENDER; atomic->object.object.flags = Atomic::COLLISIONTEST | Atomic::RENDER;
atomic->constructPlugins(); atomic->constructPlugins();
@ -603,7 +431,7 @@ Atomic::destroy(void)
this->geometry->destroy(); this->geometry->destroy();
if(this->clump) if(this->clump)
this->inClump.remove(); this->inClump.remove();
this->setFrame(NULL); this->setFrame(nil);
free(this); free(this);
} }
@ -612,7 +440,7 @@ Atomic::removeFromClump(void)
{ {
if(this->clump){ if(this->clump){
this->inClump.remove(); this->inClump.remove();
this->clump = NULL; this->clump = nil;
} }
} }
@ -640,13 +468,26 @@ Atomic::streamReadClump(Stream *stream,
{ {
int32 buf[4]; int32 buf[4];
uint32 version; 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); stream->read(buf, version < 0x30400 ? 12 : 16);
Atomic *atomic = Atomic::create(); Atomic *atomic = Atomic::create();
if(atomic == nil)
return nil;
atomic->setFrame(frameList[buf[0]]); atomic->setFrame(frameList[buf[0]]);
if(version < 0x30400){ 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); atomic->geometry = Geometry::streamRead(stream);
if(atomic->geometry == nil){
// TODO: free
return nil;
}
}else }else
atomic->geometry = geometryList[buf[1]]; atomic->geometry = geometryList[buf[1]];
atomic->object.object.flags = buf[2]; 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 }; int32 buf[4] = { 0, 0, 0, 0 };
Clump *c = this->clump; Clump *c = this->clump;
if(c == NULL) if(c == nil)
return false; return false;
writeChunkHeader(stream, ID_ATOMIC, this->streamGetSize()); writeChunkHeader(stream, ID_ATOMIC, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, rw::version < 0x30400 ? 12 : 16); writeChunkHeader(stream, ID_STRUCT, rw::version < 0x30400 ? 12 : 16);
@ -737,7 +578,7 @@ static int32
getSizeAtomicRights(void *object, int32, int32) getSizeAtomicRights(void *object, int32, int32)
{ {
Atomic *atomic = (Atomic*)object; Atomic *atomic = (Atomic*)object;
if(atomic->pipeline == NULL || atomic->pipeline->pluginID == 0) if(atomic->pipeline == nil || atomic->pipeline->pluginID == 0)
return -1; return -1;
return 8; return 8;
} }
@ -745,272 +586,11 @@ getSizeAtomicRights(void *object, int32, int32)
void void
registerAtomicRightsPlugin(void) registerAtomicRightsPlugin(void)
{ {
Atomic::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL); Atomic::registerPlugin(0, ID_RIGHTTORENDER, nil, nil, nil);
Atomic::registerPluginStream(ID_RIGHTTORENDER, Atomic::registerPluginStream(ID_RIGHTTORENDER,
readAtomicRights, readAtomicRights,
writeAtomicRights, writeAtomicRights,
getSizeAtomicRights); 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 <cstdio>
#include <assert.h> #include <cstdlib>
#include <cassert>
#include "rwbase.h" #include "rwbase.h"
#include "rwplg.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 <cmath>
#include "rwbase.h" #include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h" #include "rwplg.h"
#include "rwpipeline.h" #include "rwpipeline.h"
#include "rwobjects.h" #include "rwobjects.h"
#define PLUGIN_ID 2
using namespace std; using namespace std;
namespace rw { namespace rw {
@ -17,7 +20,10 @@ Geometry*
Geometry::create(int32 numVerts, int32 numTris, uint32 flags) Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
{ {
Geometry *geo = (Geometry*)malloc(PluginBase::s_size); 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->object.init(Geometry::ID, 0);
geo->geoflags = flags & 0xFF00FFFF; geo->geoflags = flags & 0xFF00FFFF;
geo->numTexCoordSets = (flags & 0xFF0000) >> 16; geo->numTexCoordSets = (flags & 0xFF0000) >> 16;
@ -28,10 +34,10 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
geo->numVertices = numVerts; geo->numVertices = numVerts;
geo->numMorphTargets = 1; geo->numMorphTargets = 1;
geo->colors = NULL; geo->colors = nil;
for(int32 i = 0; i < geo->numTexCoordSets; i++) for(int32 i = 0; i < geo->numTexCoordSets; i++)
geo->texCoords[i] = NULL; geo->texCoords[i] = nil;
geo->triangles = NULL; geo->triangles = nil;
if(!(geo->geoflags & NATIVE) && geo->numVertices){ if(!(geo->geoflags & NATIVE) && geo->numVertices){
if(geo->geoflags & PRELIT) if(geo->geoflags & PRELIT)
geo->colors = new uint8[4*geo->numVertices]; geo->colors = new uint8[4*geo->numVertices];
@ -45,24 +51,23 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
MorphTarget *m = geo->morphTargets; MorphTarget *m = geo->morphTargets;
m->boundingSphere.center.set(0.0f, 0.0f, 0.0f); m->boundingSphere.center.set(0.0f, 0.0f, 0.0f);
m->boundingSphere.radius = 0.0f; m->boundingSphere.radius = 0.0f;
m->vertices = NULL; m->vertices = nil;
m->normals = NULL; m->normals = nil;
if(!(geo->geoflags & NATIVE) && geo->numVertices){ if(!(geo->geoflags & NATIVE) && geo->numVertices){
m->vertices = new float32[3*geo->numVertices]; m->vertices = new float32[3*geo->numVertices];
if(geo->geoflags & NORMALS) if(geo->geoflags & NORMALS)
m->normals = new float32[3*geo->numVertices]; m->normals = new float32[3*geo->numVertices];
} }
geo->numMaterials = 0; geo->numMaterials = 0;
geo->materialList = NULL; geo->materialList = nil;
geo->meshHeader = NULL; geo->meshHeader = nil;
geo->instData = NULL; geo->instData = nil;
geo->refCount = 1; geo->refCount = 1;
geo->constructPlugins(); geo->constructPlugins();
return geo; return geo;
} }
void void
Geometry::destroy(void) Geometry::destroy(void)
{ {
@ -101,10 +106,15 @@ Geometry::streamRead(Stream *stream)
{ {
uint32 version; uint32 version;
GeoStreamData buf; 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)); stream->read(&buf, sizeof(buf));
Geometry *geo = Geometry::create(buf.numVertices, Geometry *geo = Geometry::create(buf.numVertices,
buf.numTriangles, buf.flags); buf.numTriangles, buf.flags);
if(geo == nil)
return nil;
geo->addMorphTargets(buf.numMorphTargets-1); geo->addMorphTargets(buf.numMorphTargets-1);
// skip surface properties // skip surface properties
if(version < 0x34000) if(version < 0x34000)
@ -137,13 +147,25 @@ Geometry::streamRead(Stream *stream)
stream->read(m->normals, 3*geo->numVertices*4); stream->read(m->normals, 3*geo->numVertices*4);
} }
assert(findChunk(stream, ID_MATLIST, NULL, NULL)); if(!findChunk(stream, ID_MATLIST, nil, nil)){
assert(findChunk(stream, ID_STRUCT, NULL, NULL)); 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->numMaterials = stream->readI32();
geo->materialList = new Material*[geo->numMaterials]; geo->materialList = new Material*[geo->numMaterials];
stream->seek(geo->numMaterials*4); // unused (-1) stream->seek(geo->numMaterials*4); // unused (-1)
for(int32 i = 0; i < geo->numMaterials; i++){ 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); geo->materialList[i] = Material::streamRead(stream);
} }
@ -217,8 +239,8 @@ Geometry::streamWrite(Stream *stream)
MorphTarget *m = &this->morphTargets[i]; MorphTarget *m = &this->morphTargets[i];
stream->write(&m->boundingSphere, 4*4); stream->write(&m->boundingSphere, 4*4);
if(!(this->geoflags & NATIVE)){ if(!(this->geoflags & NATIVE)){
stream->writeI32(m->vertices != NULL); stream->writeI32(m->vertices != nil);
stream->writeI32(m->normals != NULL); stream->writeI32(m->normals != nil);
if(m->vertices) if(m->vertices)
stream->write(m->vertices, stream->write(m->vertices,
3*this->numVertices*4); 3*this->numVertices*4);
@ -270,8 +292,8 @@ Geometry::addMorphTargets(int32 n)
this->morphTargets = morphTargets; this->morphTargets = morphTargets;
for(int32 i = this->numMorphTargets; i < n; i++){ for(int32 i = this->numMorphTargets; i < n; i++){
MorphTarget *m = &morphTargets[i]; MorphTarget *m = &morphTargets[i];
m->vertices = NULL; m->vertices = nil;
m->normals = NULL; m->normals = nil;
if(!(this->geoflags & NATIVE)){ if(!(this->geoflags & NATIVE)){
m->vertices = new float32[3*this->numVertices]; m->vertices = new float32[3*this->numVertices];
if(this->geoflags & NORMALS) if(this->geoflags & NORMALS)
@ -344,7 +366,7 @@ void
Geometry::generateTriangles(int8 *adc) Geometry::generateTriangles(int8 *adc)
{ {
MeshHeader *header = this->meshHeader; MeshHeader *header = this->meshHeader;
assert(header != NULL); assert(header != nil);
this->numTriangles = 0; this->numTriangles = 0;
Mesh *m = header->mesh; Mesh *m = header->mesh;
@ -452,7 +474,7 @@ Geometry::buildMeshes(void)
void void
Geometry::removeUnusedMaterials(void) Geometry::removeUnusedMaterials(void)
{ {
if(this->meshHeader == NULL) if(this->meshHeader == nil)
return; return;
MeshHeader *mh = this->meshHeader; MeshHeader *mh = this->meshHeader;
int32 *map = new int32[this->numMaterials]; int32 *map = new int32[this->numMaterials];
@ -515,13 +537,16 @@ Material*
Material::create(void) Material::create(void)
{ {
Material *mat = (Material*)malloc(PluginBase::s_size); Material *mat = (Material*)malloc(PluginBase::s_size);
assert(mat != NULL); if(mat == nil){
mat->texture = NULL; RWERROR((ERR_ALLOC, PluginBase::s_size));
return nil;
}
mat->texture = nil;
memset(&mat->color, 0xFF, 4); memset(&mat->color, 0xFF, 4);
mat->surfaceProps.ambient = 1.0f; mat->surfaceProps.ambient = 1.0f;
mat->surfaceProps.specular = 1.0f; mat->surfaceProps.specular = 1.0f;
mat->surfaceProps.diffuse = 1.0f; mat->surfaceProps.diffuse = 1.0f;
mat->pipeline = NULL; mat->pipeline = nil;
mat->refCount = 1; mat->refCount = 1;
mat->constructPlugins(); mat->constructPlugins();
return mat; return mat;
@ -531,6 +556,10 @@ Material*
Material::clone(void) Material::clone(void)
{ {
Material *mat = Material::create(); Material *mat = Material::create();
if(mat == nil){
RWERROR((ERR_ALLOC, PluginBase::s_size));
return nil;
}
mat->color = this->color; mat->color = this->color;
mat->surfaceProps = this->surfaceProps; mat->surfaceProps = this->surfaceProps;
if(this->texture){ if(this->texture){
@ -570,9 +599,14 @@ Material::streamRead(Stream *stream)
uint32 length, version; uint32 length, version;
MatStreamData buf; 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)); stream->read(&buf, sizeof(buf));
Material *mat = Material::create(); Material *mat = Material::create();
if(mat == nil)
return nil;
mat->color = buf.color; mat->color = buf.color;
if(version < 0x30400){ if(version < 0x30400){
mat->surfaceProps.ambient = 1.0f; mat->surfaceProps.ambient = 1.0f;
@ -586,8 +620,16 @@ Material::streamRead(Stream *stream)
mat->surfaceProps.diffuse = surfaceProps[2]; mat->surfaceProps.diffuse = surfaceProps[2];
} }
if(buf.textured){ 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); mat->texture = Texture::streamRead(stream);
if(mat->texture == nil){
// TODO: fre
return nil;
}
} }
materialRights[0] = 0; materialRights[0] = 0;
@ -609,7 +651,7 @@ Material::streamWrite(Stream *stream)
buf.color = this->color; buf.color = this->color;
buf.flags = 0; buf.flags = 0;
buf.unused = 0; buf.unused = 0;
buf.textured = this->texture != NULL; buf.textured = this->texture != nil;
stream->write(&buf, sizeof(buf)); stream->write(&buf, sizeof(buf));
if(rw::version >= 0x30400){ if(rw::version >= 0x30400){
@ -663,7 +705,7 @@ static int32
getSizeMaterialRights(void *object, int32, int32) getSizeMaterialRights(void *object, int32, int32)
{ {
Material *material = (Material*)object; Material *material = (Material*)object;
if(material->pipeline == NULL || material->pipeline->pluginID == 0) if(material->pipeline == nil || material->pipeline->pluginID == 0)
return -1; return -1;
return 8; return 8;
} }
@ -671,7 +713,7 @@ getSizeMaterialRights(void *object, int32, int32)
void void
registerMaterialRightsPlugin(void) registerMaterialRightsPlugin(void)
{ {
Material::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL); Material::registerPlugin(0, ID_RIGHTTORENDER, nil, nil, nil);
Material::registerPluginStream(ID_RIGHTTORENDER, Material::registerPluginStream(ID_RIGHTTORENDER,
readMaterialRights, readMaterialRights,
writeMaterialRights, 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 <cctype>
#include "rwbase.h" #include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h" #include "rwplg.h"
#include "rwpipeline.h" #include "rwpipeline.h"
#include "rwobjects.h" #include "rwobjects.h"
@ -21,6 +22,8 @@ using namespace std;
namespace rw { namespace rw {
#define PLUGIN_ID 0
int32 version = 0x36003; int32 version = 0x36003;
int32 build = 0xFFFF; int32 build = 0xFFFF;
#ifdef RW_PS2 #ifdef RW_PS2
@ -665,7 +668,11 @@ StreamFile*
StreamFile::open(const char *path, const char *mode) StreamFile::open(const char *path, const char *mode)
{ {
this->file = fopen(path, mode); this->file = fopen(path, mode);
return this->file ? this : NULL; if(this->file == NULL){
RWERROR((ERR_FILE, path));
return NULL;
}
return this;
} }
void void
@ -758,10 +765,8 @@ findPointer(void *p, void **list, int32 num)
int i; int i;
for(i = 0; i < num; i++) for(i = 0; i < num; i++)
if(list[i] == p) if(list[i] == p)
goto found;
return -1;
found:
return i; return i;
return -1;
} }
uint8* uint8*

View File

@ -33,6 +33,8 @@ typedef int32 bool32;
typedef uint8 byte; typedef uint8 byte;
typedef uint32 uint; typedef uint32 uint;
#define nil NULL
#define nelem(A) (sizeof(A) / sizeof A[0]) #define nelem(A) (sizeof(A) / sizeof A[0])
struct RGBA struct RGBA
@ -284,6 +286,16 @@ enum PluginID
ID_VERTEXFMT = 0x511, ID_VERTEXFMT = 0x511,
}; };
#define ECODE(c, s) c,
enum Errors
{
ERR_NONE = 0x80000000,
#include "base.err"
};
#undef ECODE
extern int version; extern int version;
extern int build; extern int build;
extern int platform; 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); uint32 streamGetSize(void);
void render(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); void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf);
}; };

View File

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