2016-06-17 00:06:37 +02:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
|
|
|
|
#include "rwbase.h"
|
|
|
|
#include "rwerror.h"
|
|
|
|
#include "rwplg.h"
|
|
|
|
#include "rwpipeline.h"
|
|
|
|
#include "rwobjects.h"
|
2016-06-21 23:16:09 +02:00
|
|
|
#include "rwengine.h"
|
2016-06-17 00:06:37 +02:00
|
|
|
|
|
|
|
#define PLUGIN_ID 0
|
|
|
|
|
|
|
|
namespace rw {
|
|
|
|
|
2016-06-21 23:16:09 +02:00
|
|
|
void
|
|
|
|
defaultBeginUpdateCB(Camera *cam)
|
|
|
|
{
|
|
|
|
engine.currentCamera = cam;
|
|
|
|
Frame::syncDirty();
|
|
|
|
DRIVER.beginUpdate(cam);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
defaultEndUpdateCB(Camera *cam)
|
|
|
|
{
|
|
|
|
DRIVER.endUpdate(cam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cameraSync(ObjectWithFrame*)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-06-23 16:39:34 +02:00
|
|
|
void
|
|
|
|
worldBeginUpdateCB(Camera *cam)
|
|
|
|
{
|
|
|
|
engine.currentWorld = cam->world;
|
|
|
|
cam->originalBeginUpdate(cam);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
worldEndUpdateCB(Camera *cam)
|
|
|
|
{
|
|
|
|
cam->originalEndUpdate(cam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
worldCameraSync(ObjectWithFrame *obj)
|
|
|
|
{
|
|
|
|
Camera *camera = (Camera*)obj;
|
|
|
|
camera->originalSync(obj);
|
|
|
|
}
|
|
|
|
|
2016-06-17 00:06:37 +02:00
|
|
|
Camera*
|
|
|
|
Camera::create(void)
|
|
|
|
{
|
|
|
|
Camera *cam = (Camera*)malloc(PluginBase::s_size);
|
2016-06-17 13:29:49 +02:00
|
|
|
if(cam == nil){
|
2016-06-17 00:06:37 +02:00
|
|
|
RWERROR((ERR_ALLOC, PluginBase::s_size));
|
2016-06-17 13:29:49 +02:00
|
|
|
return nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
cam->object.object.init(Camera::ID, 0);
|
2016-06-21 23:16:09 +02:00
|
|
|
cam->object.syncCB = cameraSync;
|
2016-06-23 16:39:34 +02:00
|
|
|
cam->beginUpdateCB = defaultBeginUpdateCB;
|
|
|
|
cam->endUpdateCB = defaultEndUpdateCB;
|
2016-06-17 00:06:37 +02: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;
|
|
|
|
cam->projection = Camera::PERSPECTIVE;
|
2016-06-23 16:39:34 +02:00
|
|
|
|
|
|
|
// clump extension
|
2016-06-17 13:29:49 +02:00
|
|
|
cam->clump = nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
cam->inClump.init();
|
2016-06-21 23:16:09 +02:00
|
|
|
|
2016-06-23 16:39:34 +02:00
|
|
|
// world extension
|
|
|
|
cam->world = nil;
|
|
|
|
cam->originalSync = cam->object.syncCB;
|
|
|
|
cam->originalBeginUpdate = cam->beginUpdateCB;
|
|
|
|
cam->originalEndUpdate = cam->endUpdateCB;
|
|
|
|
cam->object.syncCB = worldCameraSync;
|
|
|
|
cam->beginUpdateCB = worldBeginUpdateCB;
|
|
|
|
cam->endUpdateCB = worldEndUpdateCB;
|
2016-06-21 23:16:09 +02:00
|
|
|
|
2016-06-17 00:06:37 +02:00
|
|
|
cam->constructPlugins();
|
|
|
|
return cam;
|
|
|
|
}
|
|
|
|
|
|
|
|
Camera*
|
|
|
|
Camera::clone(void)
|
|
|
|
{
|
|
|
|
Camera *cam = Camera::create();
|
2016-06-17 13:29:49 +02:00
|
|
|
if(cam == nil)
|
|
|
|
return nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
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;
|
2016-06-17 13:29:49 +02:00
|
|
|
if(!findChunk(stream, ID_STRUCT, nil, nil)){
|
2016-06-17 00:06:37 +02:00
|
|
|
RWERROR((ERR_CHUNK, "STRUCT"));
|
2016-06-17 13:29:49 +02:00
|
|
|
return nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
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;
|
2016-06-17 13:29:49 +02:00
|
|
|
if(cam->streamReadPlugins(stream))
|
|
|
|
return cam;
|
|
|
|
cam->destroy();
|
|
|
|
return nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2016-06-23 16:39:34 +02:00
|
|
|
// TODO: remove
|
2016-06-17 00:06:37 +02: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;
|
|
|
|
}
|
2016-06-21 23:16:09 +02:00
|
|
|
}else if(rw::platform == PLATFORM_WDGL || rw::platform == PLATFORM_GL3){
|
|
|
|
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+this->nearPlane)*invz;
|
|
|
|
this->projMat[11] = 1.0f;
|
|
|
|
|
|
|
|
this->projMat[12] = 0.0f;
|
|
|
|
this->projMat[13] = 0.0f;
|
|
|
|
this->projMat[14] = -2.0f*this->nearPlane*this->farPlane*invz;
|
|
|
|
this->projMat[15] = 0.0f;
|
|
|
|
}else{
|
|
|
|
}
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|