2014-12-18 17:26:57 +01:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
2014-12-19 22:58:10 +01:00
|
|
|
#include <cassert>
|
2016-01-13 08:58:15 +01:00
|
|
|
#include <cmath>
|
2014-12-18 17:26:57 +01:00
|
|
|
|
|
|
|
#include "rwbase.h"
|
|
|
|
#include "rwplugin.h"
|
2015-07-11 23:48:11 +02:00
|
|
|
#include "rwpipeline.h"
|
2014-12-23 15:59:14 +01:00
|
|
|
#include "rwobjects.h"
|
2015-08-03 18:30:10 +02:00
|
|
|
#include "rwps2.h"
|
|
|
|
#include "rwogl.h"
|
2015-09-06 13:31:42 +02:00
|
|
|
#include "rwxbox.h"
|
2015-09-07 14:50:10 +02:00
|
|
|
#include "rwd3d8.h"
|
2015-09-06 13:31:42 +02:00
|
|
|
#include "rwd3d9.h"
|
2014-12-18 17:26:57 +01:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2015-01-25 22:27:03 +01:00
|
|
|
namespace rw {
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-02-13 00:52:32 +01:00
|
|
|
LinkList Frame::dirtyList;
|
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
Frame*
|
|
|
|
Frame::create(void)
|
|
|
|
{
|
|
|
|
Frame *f = (Frame*)malloc(PluginBase::s_size);
|
2016-01-13 08:58:15 +01:00
|
|
|
assert(f != NULL);
|
|
|
|
f->object.init(Frame::ID, 0);
|
2016-01-11 18:22:59 +01:00
|
|
|
f->objectList.init();
|
|
|
|
f->child = NULL;
|
|
|
|
f->next = NULL;
|
2016-02-13 00:52:32 +01:00
|
|
|
f->root = f;
|
2016-02-14 20:56:05 +01:00
|
|
|
f->matrix.setIdentity();
|
|
|
|
f->ltm.setIdentity();
|
2016-01-11 18:22:59 +01:00
|
|
|
f->constructPlugins();
|
|
|
|
return f;
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2016-01-12 00:38:36 +01:00
|
|
|
Frame*
|
|
|
|
Frame::cloneHierarchy(void)
|
|
|
|
{
|
|
|
|
Frame *frame = this->cloneAndLink(NULL);
|
|
|
|
frame->purgeClone();
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
void
|
|
|
|
Frame::destroy(void)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-12 00:38:36 +01:00
|
|
|
this->destructPlugins();
|
|
|
|
Frame *parent = this->getParent();
|
|
|
|
Frame *child;
|
|
|
|
if(parent){
|
|
|
|
// remove from child list
|
2016-01-13 08:58:15 +01:00
|
|
|
child = parent->child;
|
|
|
|
if(child == this)
|
|
|
|
parent->child = this->next;
|
|
|
|
else{
|
|
|
|
for(child = child->next; child != this; child = child->next)
|
|
|
|
;
|
|
|
|
child->next = this->next;
|
2016-01-12 00:38:36 +01:00
|
|
|
}
|
|
|
|
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;
|
2016-01-13 08:58:15 +01:00
|
|
|
for(Frame *child = this->child; child; child = next){
|
|
|
|
next = child->next;
|
|
|
|
child->destroyHierarchy();
|
|
|
|
}
|
2016-01-11 18:22:59 +01:00
|
|
|
this->destructPlugins();
|
|
|
|
free(this);
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Frame*
|
2016-01-24 01:42:51 +01:00
|
|
|
Frame::addChild(Frame *child, bool32 append)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-02-13 00:52:32 +01:00
|
|
|
Frame *c;
|
|
|
|
if(child->getParent())
|
|
|
|
child->removeChild();
|
2016-01-24 01:42:51 +01:00
|
|
|
if(append){
|
|
|
|
if(this->child == NULL)
|
|
|
|
this->child = child;
|
|
|
|
else{
|
2016-02-13 00:52:32 +01:00
|
|
|
for(c = this->child; c->next; c = c->next);
|
|
|
|
c->next = child;
|
2016-01-24 01:42:51 +01:00
|
|
|
}
|
|
|
|
child->next = NULL;
|
|
|
|
}else{
|
|
|
|
child->next = this->child;
|
2014-12-18 17:26:57 +01:00
|
|
|
this->child = child;
|
|
|
|
}
|
2016-01-11 11:23:26 +01:00
|
|
|
child->object.parent = this;
|
2014-12-18 17:26:57 +01:00
|
|
|
child->root = this->root;
|
2016-02-13 00:52:32 +01:00
|
|
|
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();
|
2014-12-18 17:26:57 +01:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2014-12-19 22:58:10 +01:00
|
|
|
Frame*
|
|
|
|
Frame::removeChild(void)
|
|
|
|
{
|
2016-01-13 08:58:15 +01:00
|
|
|
Frame *parent = this->getParent();
|
2016-02-13 00:52:32 +01:00
|
|
|
Frame *child = parent->child;
|
|
|
|
if(child == this)
|
2014-12-19 22:58:10 +01:00
|
|
|
parent->child = this->next;
|
|
|
|
else{
|
2016-02-13 00:52:32 +01:00
|
|
|
while(child->next != this)
|
|
|
|
child = child->next;
|
|
|
|
child->next = this->next;
|
2014-12-19 22:58:10 +01:00
|
|
|
}
|
2016-02-13 00:52:32 +01:00
|
|
|
this->object.parent = this->next = NULL;
|
|
|
|
this->root = this;
|
|
|
|
for(child = this->child; child; child = child->next)
|
|
|
|
child->setHierarchyRoot(this);
|
|
|
|
this->updateObjects();
|
2014-12-19 22:58:10 +01:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-02-13 00:52:32 +01:00
|
|
|
static void
|
|
|
|
syncRecurse(Frame *frame, uint8 flags)
|
|
|
|
{
|
|
|
|
uint8 flg;
|
|
|
|
for(; frame; frame = frame->next){
|
|
|
|
flg = flags | frame->object.privateFlags;
|
|
|
|
if(flg & Frame::SUBTREESYNCLTM){
|
2016-02-14 20:56:05 +01:00
|
|
|
Matrix::mult(&frame->ltm, &frame->getParent()->ltm, &frame->matrix);
|
2016-02-13 00:52:32 +01:00
|
|
|
frame->object.privateFlags &= ~Frame::SUBTREESYNCLTM;
|
|
|
|
}
|
|
|
|
syncRecurse(frame->child, flg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-12 17:42:44 +01:00
|
|
|
void
|
2016-02-13 00:52:32 +01:00
|
|
|
Frame::syncHierarchyLTM(void)
|
2015-01-12 17:42:44 +01:00
|
|
|
{
|
2016-02-13 00:52:32 +01:00
|
|
|
Frame *child;
|
|
|
|
uint8 flg;
|
|
|
|
if(this->object.privateFlags & Frame::SUBTREESYNCLTM)
|
2016-02-14 20:56:05 +01:00
|
|
|
this->ltm = this->matrix;
|
2016-02-13 00:52:32 +01:00
|
|
|
for(child = this->child; child; child = child->next){
|
|
|
|
flg = this->object.privateFlags | child->object.privateFlags;
|
|
|
|
if(flg & Frame::SUBTREESYNCLTM){
|
2016-02-14 20:56:05 +01:00
|
|
|
Matrix::mult(&child->ltm, &this->ltm, &child->matrix);
|
2016-02-13 00:52:32 +01:00
|
|
|
child->object.privateFlags &= ~Frame::SUBTREESYNCLTM;
|
|
|
|
}
|
|
|
|
syncRecurse(child, flg);
|
2015-01-12 17:42:44 +01:00
|
|
|
}
|
2016-02-13 00:52:32 +01:00
|
|
|
this->object.privateFlags &= ~Frame::SYNCLTM;
|
2015-01-12 17:42:44 +01:00
|
|
|
}
|
|
|
|
|
2016-02-14 20:56:05 +01:00
|
|
|
Matrix*
|
2016-02-13 00:52:32 +01:00
|
|
|
Frame::getLTM(void)
|
2015-01-17 15:15:03 +01:00
|
|
|
{
|
2016-02-13 00:52:32 +01:00
|
|
|
if(this->root->object.privateFlags & Frame::HIERARCHYSYNCLTM)
|
|
|
|
this->root->syncHierarchyLTM();
|
2016-02-14 20:56:05 +01:00
|
|
|
return &this->ltm;
|
2015-01-17 15:15:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-02-13 00:52:32 +01:00
|
|
|
Frame::updateObjects(void)
|
2015-01-17 15:15:03 +01:00
|
|
|
{
|
2016-02-13 00:52:32 +01:00
|
|
|
if((this->root->object.privateFlags & HIERARCHYSYNC) == 0)
|
|
|
|
Frame::dirtyList.add(&this->inDirtyList);
|
|
|
|
this->root->object.privateFlags |= HIERARCHYSYNC;
|
|
|
|
this->object.privateFlags |= SUBTREESYNC;
|
2015-01-17 15:15:03 +01:00
|
|
|
}
|
|
|
|
|
2016-01-12 00:38:36 +01:00
|
|
|
void
|
|
|
|
Frame::setHierarchyRoot(Frame *root)
|
|
|
|
{
|
2016-01-13 08:58:15 +01:00
|
|
|
this->root = root;
|
|
|
|
for(Frame *child = this->child; child; child = child->next)
|
2016-01-12 00:38:36 +01:00
|
|
|
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);
|
2016-02-14 20:56:05 +01:00
|
|
|
frame->matrix = this->matrix;
|
|
|
|
//memcpy(frame->matrix, this->matrix, sizeof(this->matrix));
|
2016-01-12 00:38:36 +01:00
|
|
|
frame->root = clonedroot;
|
|
|
|
this->root = frame; // Remember cloned frame
|
|
|
|
for(Frame *child = this->child; child; child = child->next){
|
2016-01-13 08:58:15 +01:00
|
|
|
Frame *clonedchild = child->cloneAndLink(clonedroot);
|
2016-01-12 00:38:36 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
static Frame*
|
|
|
|
sizeCB(Frame *f, void *size)
|
|
|
|
{
|
|
|
|
*(int32*)size += f->streamGetPluginSize();
|
|
|
|
f->forAllChildren(sizeCB, size);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2015-12-18 01:10:42 +01:00
|
|
|
Frame**
|
2014-12-18 17:26:57 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-01-09 20:17:32 +01:00
|
|
|
//
|
|
|
|
// Clump
|
|
|
|
//
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
Clump*
|
|
|
|
Clump::create(void)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-11 18:22:59 +01:00
|
|
|
Clump *clump = (Clump*)malloc(PluginBase::s_size);
|
2016-01-13 08:58:15 +01:00
|
|
|
assert(clump != NULL);
|
|
|
|
clump->object.init(Clump::ID, 0);
|
2016-01-11 18:22:59 +01:00
|
|
|
clump->atomics.init();
|
|
|
|
clump->lights.init();
|
2016-01-13 08:58:15 +01:00
|
|
|
clump->cameras.init();
|
2016-01-11 18:22:59 +01:00
|
|
|
clump->constructPlugins();
|
|
|
|
return clump;
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
Clump*
|
|
|
|
Clump::clone(void)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-11 18:22:59 +01:00
|
|
|
Clump *clump = Clump::create();
|
2016-01-12 00:38:36 +01:00
|
|
|
Frame *root = this->getFrame()->cloneHierarchy();
|
|
|
|
clump->setFrame(root);
|
|
|
|
FORLIST(lnk, this->atomics){
|
|
|
|
Atomic *a = Atomic::fromClump(lnk);
|
|
|
|
Atomic *atomic = a->clone();
|
|
|
|
atomic->setFrame(a->getFrame()->root);
|
|
|
|
clump->addAtomic(atomic);
|
|
|
|
}
|
|
|
|
root->purgeClone();
|
2016-01-11 18:22:59 +01:00
|
|
|
clump->copyPlugins(this);
|
|
|
|
return clump;
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
void
|
|
|
|
Clump::destroy(void)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-12 00:38:36 +01:00
|
|
|
Frame *f;
|
2014-12-25 11:14:36 +01:00
|
|
|
this->destructPlugins();
|
2016-01-12 00:38:36 +01:00
|
|
|
FORLIST(lnk, this->atomics)
|
|
|
|
Atomic::fromClump(lnk)->destroy();
|
|
|
|
FORLIST(lnk, this->lights)
|
|
|
|
Light::fromClump(lnk)->destroy();
|
2016-01-13 08:58:15 +01:00
|
|
|
FORLIST(lnk, this->cameras)
|
|
|
|
Camera::fromClump(lnk)->destroy();
|
2016-01-12 00:38:36 +01:00
|
|
|
if(f = this->getFrame())
|
|
|
|
f->destroyHierarchy();
|
2016-01-11 18:22:59 +01:00
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
Clump*
|
2014-12-27 23:18:10 +01:00
|
|
|
Clump::streamRead(Stream *stream)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
|
|
|
uint32 length, version;
|
|
|
|
int32 buf[3];
|
|
|
|
Clump *clump;
|
2015-01-25 22:27:03 +01:00
|
|
|
assert(findChunk(stream, ID_STRUCT, &length, &version));
|
2016-01-11 18:22:59 +01:00
|
|
|
clump = Clump::create();
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->read(buf, length);
|
2016-01-11 18:22:59 +01:00
|
|
|
int32 numAtomics = buf[0];
|
|
|
|
int32 numLights = 0;
|
2016-01-13 08:58:15 +01:00
|
|
|
int32 numCameras = 0;
|
|
|
|
if(version > 0x33000){
|
2016-01-11 18:22:59 +01:00
|
|
|
numLights = buf[1];
|
2016-01-13 08:58:15 +01:00
|
|
|
numCameras = buf[2];
|
|
|
|
}
|
2014-12-18 17:26:57 +01:00
|
|
|
|
|
|
|
// Frame list
|
|
|
|
Frame **frameList;
|
|
|
|
int32 numFrames;
|
|
|
|
clump->frameListStreamRead(stream, &frameList, &numFrames);
|
2016-01-13 08:58:15 +01:00
|
|
|
clump->setFrame(frameList[0]);
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2014-12-25 11:14:36 +01:00
|
|
|
Geometry **geometryList = 0;
|
2015-08-16 23:23:41 +02:00
|
|
|
if(version >= 0x30400){
|
|
|
|
// Geometry list
|
|
|
|
int32 numGeometries = 0;
|
|
|
|
assert(findChunk(stream, ID_GEOMETRYLIST, NULL, NULL));
|
|
|
|
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
|
|
|
|
numGeometries = stream->readI32();
|
|
|
|
if(numGeometries)
|
|
|
|
geometryList = new Geometry*[numGeometries];
|
|
|
|
for(int32 i = 0; i < numGeometries; i++){
|
|
|
|
assert(findChunk(stream, ID_GEOMETRY, NULL, NULL));
|
|
|
|
geometryList[i] = Geometry::streamRead(stream);
|
|
|
|
}
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Atomics
|
2016-01-11 18:22:59 +01:00
|
|
|
for(int32 i = 0; i < numAtomics; i++){
|
2015-01-25 22:27:03 +01:00
|
|
|
assert(findChunk(stream, ID_ATOMIC, NULL, NULL));
|
2016-01-11 18:22:59 +01:00
|
|
|
Atomic *a = Atomic::streamReadClump(stream, frameList, geometryList);
|
|
|
|
clump->addAtomic(a);
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Lights
|
2016-01-11 18:22:59 +01:00
|
|
|
for(int32 i = 0; i < numLights; i++){
|
2014-12-18 17:26:57 +01:00
|
|
|
int32 frm;
|
2015-01-25 22:27:03 +01:00
|
|
|
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
|
2014-12-27 23:18:10 +01:00
|
|
|
frm = stream->readI32();
|
2015-01-25 22:27:03 +01:00
|
|
|
assert(findChunk(stream, ID_LIGHT, NULL, NULL));
|
2016-01-11 18:22:59 +01:00
|
|
|
Light *l = Light::streamRead(stream);
|
|
|
|
l->setFrame(frameList[frm]);
|
|
|
|
clump->addLight(l);
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
// Cameras
|
|
|
|
for(int32 i = 0; i < numCameras; i++){
|
|
|
|
int32 frm;
|
|
|
|
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
|
|
|
|
frm = stream->readI32();
|
|
|
|
assert(findChunk(stream, ID_CAMERA, NULL, NULL));
|
|
|
|
Camera *cam = Camera::streamRead(stream);
|
|
|
|
cam->setFrame(frameList[frm]);
|
|
|
|
clump->addCamera(cam);
|
|
|
|
}
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
delete[] frameList;
|
|
|
|
|
|
|
|
clump->streamReadPlugins(stream);
|
|
|
|
return clump;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-12-27 23:18:10 +01:00
|
|
|
Clump::streamWrite(Stream *stream)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
|
|
|
int size = this->streamGetSize();
|
2015-01-25 22:27:03 +01:00
|
|
|
writeChunkHeader(stream, ID_CLUMP, size);
|
2016-01-11 18:22:59 +01:00
|
|
|
int32 numAtomics = this->countAtomics();
|
|
|
|
int32 numLights = this->countLights();
|
2016-01-24 01:42:51 +01:00
|
|
|
int32 numCameras = this->countCameras();
|
|
|
|
int buf[3] = { numAtomics, numLights, numCameras };
|
2015-08-15 23:22:51 +02:00
|
|
|
size = version > 0x33000 ? 12 : 4;
|
2015-01-25 22:27:03 +01:00
|
|
|
writeChunkHeader(stream, ID_STRUCT, size);
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->write(buf, size);
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
int32 numFrames = this->getFrame()->count();
|
2014-12-18 17:26:57 +01:00
|
|
|
Frame **flist = new Frame*[numFrames];
|
2016-01-13 08:58:15 +01:00
|
|
|
makeFrameList(this->getFrame(), flist);
|
2014-12-18 17:26:57 +01:00
|
|
|
this->frameListStreamWrite(stream, flist, numFrames);
|
|
|
|
|
2015-08-16 23:23:41 +02:00
|
|
|
if(rw::version >= 0x30400){
|
|
|
|
size = 12+4;
|
2016-01-11 18:22:59 +01:00
|
|
|
FORLIST(lnk, this->atomics)
|
|
|
|
size += 12 + Atomic::fromClump(lnk)->geometry->streamGetSize();
|
2015-08-16 23:23:41 +02:00
|
|
|
writeChunkHeader(stream, ID_GEOMETRYLIST, size);
|
|
|
|
writeChunkHeader(stream, ID_STRUCT, 4);
|
2016-01-11 18:22:59 +01:00
|
|
|
stream->writeI32(numAtomics); // same as numGeometries
|
|
|
|
FORLIST(lnk, this->atomics)
|
|
|
|
Atomic::fromClump(lnk)->geometry->streamWrite(stream);
|
2015-08-16 23:23:41 +02:00
|
|
|
}
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
FORLIST(lnk, this->atomics)
|
|
|
|
Atomic::fromClump(lnk)->streamWriteClump(stream, flist, numFrames);
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
FORLIST(lnk, this->lights){
|
|
|
|
Light *l = Light::fromClump(lnk);
|
2016-01-13 08:58:15 +01:00
|
|
|
int frm = findPointer(l->getFrame(), (void**)flist, numFrames);
|
2014-12-18 17:26:57 +01:00
|
|
|
if(frm < 0)
|
|
|
|
return false;
|
2015-01-25 22:27:03 +01:00
|
|
|
writeChunkHeader(stream, ID_STRUCT, 4);
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->writeI32(frm);
|
2014-12-18 17:26:57 +01:00
|
|
|
l->streamWrite(stream);
|
|
|
|
}
|
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
FORLIST(lnk, this->cameras){
|
|
|
|
Camera *c = Camera::fromClump(lnk);
|
|
|
|
int frm = findPointer(c->getFrame(), (void**)flist, numFrames);
|
|
|
|
if(frm < 0)
|
|
|
|
return false;
|
|
|
|
writeChunkHeader(stream, ID_STRUCT, 4);
|
|
|
|
stream->writeI32(frm);
|
|
|
|
c->streamWrite(stream);
|
|
|
|
}
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
delete[] flist;
|
|
|
|
|
|
|
|
this->streamWritePlugins(stream);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct FrameStreamData
|
|
|
|
{
|
2016-02-14 20:56:05 +01:00
|
|
|
V3d right, up, at, pos;
|
2014-12-18 17:26:57 +01:00
|
|
|
int32 parent;
|
|
|
|
int32 matflag;
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32
|
|
|
|
Clump::streamGetSize(void)
|
|
|
|
{
|
|
|
|
uint32 size = 0;
|
|
|
|
size += 12; // Struct
|
|
|
|
size += 4; // numAtomics
|
2015-08-15 23:22:51 +02:00
|
|
|
if(version > 0x33000)
|
2014-12-18 17:26:57 +01:00
|
|
|
size += 8; // numLights, numCameras
|
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
// Frame list
|
|
|
|
int32 numFrames = this->getFrame()->count();
|
2014-12-18 17:26:57 +01:00
|
|
|
size += 12 + 12 + 4 + numFrames*(sizeof(FrameStreamData)+12);
|
2016-01-13 08:58:15 +01:00
|
|
|
sizeCB(this->getFrame(), (void*)&size);
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2015-08-16 23:23:41 +02:00
|
|
|
if(rw::version >= 0x30400){
|
2016-01-13 08:58:15 +01:00
|
|
|
// Geometry list
|
2015-08-16 23:23:41 +02:00
|
|
|
size += 12 + 12 + 4;
|
2016-01-11 18:22:59 +01:00
|
|
|
FORLIST(lnk, this->atomics)
|
|
|
|
size += 12 + Atomic::fromClump(lnk)->geometry->streamGetSize();
|
2015-08-16 23:23:41 +02:00
|
|
|
}
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
// Atomics
|
2016-01-11 18:22:59 +01:00
|
|
|
FORLIST(lnk, this->atomics)
|
|
|
|
size += 12 + Atomic::fromClump(lnk)->streamGetSize();
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
// Lights
|
2016-01-11 18:22:59 +01:00
|
|
|
FORLIST(lnk, this->lights)
|
|
|
|
size += 16 + 12 + Light::fromClump(lnk)->streamGetSize();
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
// Cameras
|
|
|
|
FORLIST(lnk, this->cameras)
|
|
|
|
size += 16 + 12 + Camera::fromClump(lnk)->streamGetSize();
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
size += 12 + this->streamGetPluginSize();
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2016-02-14 20:56:05 +01:00
|
|
|
void
|
|
|
|
Clump::render(void)
|
|
|
|
{
|
|
|
|
Atomic *a;
|
|
|
|
FORLIST(lnk, this->atomics){
|
|
|
|
a = Atomic::fromClump(lnk);
|
|
|
|
if(a->object.flags & Atomic::RENDER)
|
|
|
|
a->render();
|
|
|
|
}
|
|
|
|
}
|
2014-12-18 17:26:57 +01:00
|
|
|
|
|
|
|
void
|
2014-12-27 23:18:10 +01:00
|
|
|
Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
|
|
|
FrameStreamData buf;
|
|
|
|
int32 numFrames = 0;
|
2015-01-25 22:27:03 +01:00
|
|
|
assert(findChunk(stream, ID_FRAMELIST, NULL, NULL));
|
|
|
|
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
|
2014-12-27 23:18:10 +01:00
|
|
|
numFrames = stream->readI32();
|
2014-12-18 17:26:57 +01:00
|
|
|
Frame **frameList = new Frame*[numFrames];
|
|
|
|
for(int32 i = 0; i < numFrames; i++){
|
|
|
|
Frame *f;
|
2016-01-11 18:22:59 +01:00
|
|
|
frameList[i] = f = Frame::create();
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->read(&buf, sizeof(buf));
|
2016-02-14 20:56:05 +01:00
|
|
|
f->matrix.right = buf.right;
|
|
|
|
f->matrix.rightw = 0.0f;
|
|
|
|
f->matrix.up = buf.up;
|
|
|
|
f->matrix.upw = 0.0f;
|
|
|
|
f->matrix.at = buf.at;
|
|
|
|
f->matrix.atw = 0.0f;
|
|
|
|
f->matrix.pos = buf.pos;
|
|
|
|
f->matrix.posw = 1.0f;
|
2016-02-13 00:52:32 +01:00
|
|
|
//f->matflag = buf.matflag;
|
2014-12-18 17:26:57 +01:00
|
|
|
if(buf.parent >= 0)
|
|
|
|
frameList[buf.parent]->addChild(f);
|
|
|
|
}
|
|
|
|
for(int32 i = 0; i < numFrames; i++)
|
|
|
|
frameList[i]->streamReadPlugins(stream);
|
|
|
|
*nf = numFrames;
|
|
|
|
*flp = frameList;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-12-27 23:18:10 +01:00
|
|
|
Clump::frameListStreamWrite(Stream *stream, Frame **frameList, int32 numFrames)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
|
|
|
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();
|
|
|
|
|
2015-01-25 22:27:03 +01:00
|
|
|
writeChunkHeader(stream, ID_FRAMELIST, size);
|
|
|
|
writeChunkHeader(stream, ID_STRUCT, structsize);
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->writeU32(numFrames);
|
2014-12-18 17:26:57 +01:00
|
|
|
for(int32 i = 0; i < numFrames; i++){
|
|
|
|
Frame *f = frameList[i];
|
2016-02-14 20:56:05 +01:00
|
|
|
buf.right = f->matrix.right;
|
|
|
|
buf.up = f->matrix.up;
|
|
|
|
buf.at = f->matrix.at;
|
|
|
|
buf.pos = f->matrix.pos;
|
2016-01-13 08:58:15 +01:00
|
|
|
buf.parent = findPointer(f->getParent(), (void**)frameList,
|
2015-08-11 21:48:23 +02:00
|
|
|
numFrames);
|
2016-02-13 00:52:32 +01:00
|
|
|
buf.matflag = 0; //f->matflag;
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->write(&buf, sizeof(buf));
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
for(int32 i = 0; i < numFrames; i++)
|
|
|
|
frameList[i]->streamWritePlugins(stream);
|
|
|
|
}
|
|
|
|
|
2015-01-09 20:17:32 +01:00
|
|
|
//
|
|
|
|
// Atomic
|
|
|
|
//
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
Atomic*
|
|
|
|
Atomic::create(void)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-11 18:22:59 +01:00
|
|
|
Atomic *atomic = (Atomic*)malloc(PluginBase::s_size);
|
2016-01-13 08:58:15 +01:00
|
|
|
assert(atomic != NULL);
|
|
|
|
atomic->object.init(Atomic::ID, 0);
|
2016-01-11 18:22:59 +01:00
|
|
|
atomic->geometry = NULL;
|
2016-02-17 23:59:05 +01:00
|
|
|
atomic->clump = NULL;
|
2016-01-11 18:22:59 +01:00
|
|
|
atomic->pipeline = NULL;
|
2016-02-13 00:52:32 +01:00
|
|
|
atomic->renderCB = Atomic::defaultRenderCB;
|
2016-02-14 20:56:05 +01:00
|
|
|
atomic->object.flags = Atomic::COLLISIONTEST | Atomic::RENDER;
|
2016-01-11 18:22:59 +01:00
|
|
|
atomic->constructPlugins();
|
2016-01-24 01:42:51 +01:00
|
|
|
|
|
|
|
// private flags:
|
|
|
|
// rpATOMICPRIVATEWORLDBOUNDDIRTY = 0x01
|
2016-01-11 18:22:59 +01:00
|
|
|
return atomic;
|
2016-01-13 08:58:15 +01:00
|
|
|
}
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
Atomic*
|
|
|
|
Atomic::clone()
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-11 18:22:59 +01:00
|
|
|
Atomic *atomic = Atomic::create();
|
2016-01-12 00:38:36 +01:00
|
|
|
atomic->object.copy(&this->object);
|
|
|
|
atomic->object.privateFlags |= 1;
|
|
|
|
if(this->geometry){
|
|
|
|
atomic->geometry = this->geometry;
|
|
|
|
atomic->geometry->refCount++;
|
|
|
|
}
|
|
|
|
atomic->pipeline = this->pipeline;
|
2016-01-11 18:22:59 +01:00
|
|
|
atomic->copyPlugins(this);
|
|
|
|
return atomic;
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
void
|
|
|
|
Atomic::destroy(void)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-11 18:22:59 +01:00
|
|
|
this->destructPlugins();
|
2016-01-12 00:38:36 +01:00
|
|
|
if(this->geometry)
|
|
|
|
this->geometry->destroy();
|
2016-02-17 23:59:05 +01:00
|
|
|
if(this->clump)
|
|
|
|
this->inClump.remove();
|
2016-01-12 00:38:36 +01:00
|
|
|
this->setFrame(NULL);
|
2016-01-11 18:22:59 +01:00
|
|
|
free(this);
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2015-01-10 22:13:27 +01:00
|
|
|
static uint32 atomicRights[2];
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
Atomic*
|
2014-12-27 23:18:10 +01:00
|
|
|
Atomic::streamReadClump(Stream *stream,
|
2014-12-18 17:26:57 +01:00
|
|
|
Frame **frameList, Geometry **geometryList)
|
|
|
|
{
|
|
|
|
int32 buf[4];
|
2015-08-16 23:23:41 +02:00
|
|
|
uint32 version;
|
|
|
|
assert(findChunk(stream, ID_STRUCT, NULL, &version));
|
|
|
|
stream->read(buf, version < 0x30400 ? 12 : 16);
|
2016-01-11 18:22:59 +01:00
|
|
|
Atomic *atomic = Atomic::create();
|
2016-01-11 11:23:26 +01:00
|
|
|
atomic->setFrame(frameList[buf[0]]);
|
2015-08-16 23:23:41 +02:00
|
|
|
if(version < 0x30400){
|
|
|
|
assert(findChunk(stream, ID_GEOMETRY, NULL, NULL));
|
|
|
|
atomic->geometry = Geometry::streamRead(stream);
|
|
|
|
}else
|
|
|
|
atomic->geometry = geometryList[buf[1]];
|
2016-02-14 20:56:05 +01:00
|
|
|
atomic->object.flags = buf[2];
|
2015-01-10 22:13:27 +01:00
|
|
|
|
|
|
|
atomicRights[0] = 0;
|
2014-12-18 17:26:57 +01:00
|
|
|
atomic->streamReadPlugins(stream);
|
2015-01-10 22:13:27 +01:00
|
|
|
if(atomicRights[0])
|
|
|
|
atomic->assertRights(atomicRights[0], atomicRights[1]);
|
2014-12-18 17:26:57 +01:00
|
|
|
return atomic;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-12-27 23:18:10 +01:00
|
|
|
Atomic::streamWriteClump(Stream *stream, Frame **frameList, int32 numFrames)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-02-14 20:56:05 +01:00
|
|
|
int32 buf[4] = { 0, 0, 0, 0 };
|
2014-12-18 17:26:57 +01:00
|
|
|
Clump *c = this->clump;
|
|
|
|
if(c == NULL)
|
|
|
|
return false;
|
2015-01-25 22:27:03 +01:00
|
|
|
writeChunkHeader(stream, ID_ATOMIC, this->streamGetSize());
|
2015-08-16 23:23:41 +02:00
|
|
|
writeChunkHeader(stream, ID_STRUCT, rw::version < 0x30400 ? 12 : 16);
|
2016-01-13 08:58:15 +01:00
|
|
|
buf[0] = findPointer(this->getFrame(), (void**)frameList, numFrames);
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2015-08-16 23:23:41 +02:00
|
|
|
if(version < 0x30400){
|
2016-02-14 20:56:05 +01:00
|
|
|
buf[1] = this->object.flags;
|
2015-08-16 23:23:41 +02:00
|
|
|
stream->write(buf, sizeof(int[3]));
|
|
|
|
this->geometry->streamWrite(stream);
|
|
|
|
}else{
|
2016-01-11 18:22:59 +01:00
|
|
|
buf[1] = 0;
|
|
|
|
FORLIST(lnk, c->atomics){
|
|
|
|
if(Atomic::fromClump(lnk)->geometry == this->geometry)
|
2015-08-16 23:23:41 +02:00
|
|
|
goto foundgeo;
|
2016-01-11 18:22:59 +01:00
|
|
|
buf[1]++;
|
|
|
|
}
|
2015-08-16 23:23:41 +02:00
|
|
|
return false;
|
|
|
|
foundgeo:
|
2016-02-14 20:56:05 +01:00
|
|
|
buf[2] = this->object.flags;
|
2015-08-16 23:23:41 +02:00
|
|
|
stream->write(buf, sizeof(buf));
|
|
|
|
}
|
2014-12-18 17:26:57 +01:00
|
|
|
|
|
|
|
this->streamWritePlugins(stream);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32
|
|
|
|
Atomic::streamGetSize(void)
|
|
|
|
{
|
2015-08-16 23:23:41 +02:00
|
|
|
uint32 size = 12 + 12 + 12 + this->streamGetPluginSize();
|
|
|
|
if(rw::version < 0x30400)
|
|
|
|
size += 12 + this->geometry->streamGetSize();
|
|
|
|
else
|
|
|
|
size += 4;
|
|
|
|
return size;
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2015-08-03 18:30:10 +02:00
|
|
|
ObjPipeline *defaultPipelines[NUM_PLATFORMS];
|
|
|
|
|
|
|
|
ObjPipeline*
|
|
|
|
Atomic::getPipeline(void)
|
|
|
|
{
|
|
|
|
return this->pipeline ?
|
|
|
|
this->pipeline :
|
2015-09-19 19:28:23 +02:00
|
|
|
defaultPipelines[platform];
|
2015-08-03 18:30:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-02-13 00:52:32 +01:00
|
|
|
Atomic::defaultRenderCB(Atomic *atomic)
|
|
|
|
{
|
|
|
|
atomic->getPipeline()->render(atomic);
|
2015-08-03 18:30:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-09 20:17:32 +01:00
|
|
|
// Atomic Rights plugin
|
|
|
|
|
|
|
|
static void
|
|
|
|
readAtomicRights(Stream *stream, int32, void *, int32, int32)
|
|
|
|
{
|
2015-01-10 22:13:27 +01:00
|
|
|
stream->read(atomicRights, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeAtomicRights(Stream *stream, int32, void *object, int32, int32)
|
|
|
|
{
|
|
|
|
Atomic *atomic = (Atomic*)object;
|
|
|
|
uint32 buffer[2];
|
|
|
|
buffer[0] = atomic->pipeline->pluginID;
|
|
|
|
buffer[1] = atomic->pipeline->pluginData;
|
|
|
|
stream->write(buffer, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
|
|
|
getSizeAtomicRights(void *object, int32, int32)
|
|
|
|
{
|
|
|
|
Atomic *atomic = (Atomic*)object;
|
|
|
|
if(atomic->pipeline == NULL || atomic->pipeline->pluginID == 0)
|
|
|
|
return -1;
|
|
|
|
return 8;
|
2015-01-09 20:17:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-25 22:27:03 +01:00
|
|
|
registerAtomicRightsPlugin(void)
|
2015-01-09 20:17:32 +01:00
|
|
|
{
|
|
|
|
Atomic::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL);
|
|
|
|
Atomic::registerPluginStream(ID_RIGHTTORENDER,
|
2015-01-10 22:13:27 +01:00
|
|
|
readAtomicRights,
|
|
|
|
writeAtomicRights,
|
|
|
|
getSizeAtomicRights);
|
2015-01-09 20:17:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Light
|
|
|
|
//
|
2014-12-18 17:26:57 +01:00
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
Light*
|
|
|
|
Light::create(int32 type)
|
|
|
|
{
|
|
|
|
Light *light = (Light*)malloc(PluginBase::s_size);
|
2016-01-13 08:58:15 +01:00
|
|
|
assert(light != NULL);
|
|
|
|
light->object.init(Light::ID, type);
|
2016-01-11 18:22:59 +01:00
|
|
|
light->radius = 0.0f;
|
2016-01-14 23:49:00 +01:00
|
|
|
light->color.red = 1.0f;
|
|
|
|
light->color.green = 1.0f;
|
|
|
|
light->color.blue = 1.0f;
|
|
|
|
light->color.alpha = 1.0f;
|
2016-01-11 18:22:59 +01:00
|
|
|
light->minusCosAngle = 1.0f;
|
|
|
|
light->object.privateFlags = 1;
|
2016-01-13 08:58:15 +01:00
|
|
|
light->object.flags = LIGHTATOMICS | LIGHTWORLD;
|
2016-01-11 18:22:59 +01:00
|
|
|
light->inClump.init();
|
|
|
|
light->constructPlugins();
|
|
|
|
return light;
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2016-01-11 18:22:59 +01:00
|
|
|
void
|
|
|
|
Light::destroy(void)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-11 18:22:59 +01:00
|
|
|
this->destructPlugins();
|
|
|
|
free(this);
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
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)
|
|
|
|
{
|
2016-01-14 23:49:00 +01:00
|
|
|
this->color.red = r;
|
|
|
|
this->color.green = g;
|
|
|
|
this->color.blue = b;
|
2016-01-13 08:58:15 +01:00
|
|
|
this->object.privateFlags = r == g && r == b;
|
|
|
|
}
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
struct LightChunkData
|
|
|
|
{
|
|
|
|
float32 radius;
|
|
|
|
float32 red, green, blue;
|
|
|
|
float32 minusCosAngle;
|
|
|
|
uint16 flags;
|
|
|
|
uint16 type;
|
|
|
|
};
|
|
|
|
|
|
|
|
Light*
|
2014-12-27 23:18:10 +01:00
|
|
|
Light::streamRead(Stream *stream)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
2016-01-13 08:58:15 +01:00
|
|
|
uint32 version;
|
2014-12-18 17:26:57 +01:00
|
|
|
LightChunkData buf;
|
2016-01-13 08:58:15 +01:00
|
|
|
assert(findChunk(stream, ID_STRUCT, NULL, &version));
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->read(&buf, sizeof(LightChunkData));
|
2016-01-11 18:22:59 +01:00
|
|
|
Light *light = Light::create(buf.type);
|
2014-12-18 17:26:57 +01:00
|
|
|
light->radius = buf.radius;
|
2016-01-13 08:58:15 +01:00
|
|
|
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);
|
2016-01-11 11:23:26 +01:00
|
|
|
light->object.flags = (uint8)buf.flags;
|
2014-12-18 17:26:57 +01:00
|
|
|
light->streamReadPlugins(stream);
|
|
|
|
return light;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-12-27 23:18:10 +01:00
|
|
|
Light::streamWrite(Stream *stream)
|
2014-12-18 17:26:57 +01:00
|
|
|
{
|
|
|
|
LightChunkData buf;
|
2015-01-25 22:27:03 +01:00
|
|
|
writeChunkHeader(stream, ID_LIGHT, this->streamGetSize());
|
|
|
|
writeChunkHeader(stream, ID_STRUCT, sizeof(LightChunkData));
|
2014-12-18 17:26:57 +01:00
|
|
|
buf.radius = this->radius;
|
2016-01-14 23:49:00 +01:00
|
|
|
buf.red = this->color.red;
|
|
|
|
buf.green = this->color.green;
|
|
|
|
buf.blue = this->color.blue;
|
2016-01-13 08:58:15 +01:00
|
|
|
if(version >= 0x30300)
|
|
|
|
buf.minusCosAngle = this->minusCosAngle;
|
|
|
|
else
|
|
|
|
buf.minusCosAngle = tan(acos(-this->minusCosAngle));
|
2016-01-11 11:23:26 +01:00
|
|
|
buf.flags = this->object.flags;
|
|
|
|
buf.type = this->object.subType;
|
2014-12-27 23:18:10 +01:00
|
|
|
stream->write(&buf, sizeof(LightChunkData));
|
2014-12-18 17:26:57 +01:00
|
|
|
|
|
|
|
this->streamWritePlugins(stream);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32
|
|
|
|
Light::streamGetSize(void)
|
|
|
|
{
|
|
|
|
return 12 + sizeof(LightChunkData) + 12 + this->streamGetPluginSize();
|
|
|
|
}
|
|
|
|
|
2016-01-13 08:58:15 +01:00
|
|
|
//
|
|
|
|
// Camera
|
|
|
|
//
|
|
|
|
|
|
|
|
Camera*
|
|
|
|
Camera::create(void)
|
|
|
|
{
|
|
|
|
Camera *cam = (Camera*)malloc(PluginBase::s_size);
|
|
|
|
cam->object.init(Camera::ID, 0);
|
2016-01-14 23:49:00 +01:00
|
|
|
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;
|
2016-02-14 20:56:05 +01:00
|
|
|
cam->projection = Camera::PERSPECTIVE;
|
2016-01-13 08:58:15 +01:00
|
|
|
cam->constructPlugins();
|
|
|
|
return cam;
|
|
|
|
}
|
|
|
|
|
|
|
|
Camera*
|
|
|
|
Camera::clone(void)
|
|
|
|
{
|
|
|
|
Camera *cam = Camera::create();
|
|
|
|
cam->object.copy(&this->object);
|
2016-01-14 23:49:00 +01:00
|
|
|
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;
|
2016-01-13 08:58:15 +01:00
|
|
|
cam->copyPlugins(this);
|
|
|
|
return cam;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Camera::destroy(void)
|
|
|
|
{
|
|
|
|
this->destructPlugins();
|
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CameraChunkData
|
|
|
|
{
|
|
|
|
V2d viewWindow;
|
|
|
|
V2d viewOffset;
|
2016-01-14 23:49:00 +01:00
|
|
|
float32 nearPlane, farPlane;
|
2016-01-13 08:58:15 +01:00
|
|
|
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;
|
2016-01-14 23:49:00 +01:00
|
|
|
cam->nearPlane = buf.nearPlane;
|
|
|
|
cam->farPlane = buf.farPlane;
|
2016-01-13 08:58:15 +01:00
|
|
|
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;
|
2016-01-14 23:49:00 +01:00
|
|
|
buf.nearPlane = this->nearPlane;
|
|
|
|
buf.farPlane = this->farPlane;
|
2016-01-13 08:58:15 +01:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2016-02-14 20:56:05 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-12-18 17:26:57 +01:00
|
|
|
}
|