mirror of https://github.com/aap/librw.git
worked on camera
This commit is contained in:
parent
dcbbdfe6b2
commit
bd06c54c57
27
src/base.cpp
27
src/base.cpp
|
@ -153,6 +153,33 @@ Matrix::invert(Matrix *m1, Matrix *m2)
|
||||||
return matrixInvert((float32*)m1, (float32*)m2);
|
return matrixInvert((float32*)m1, (float32*)m2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Matrix::invertOrthonormal(Matrix *m1, Matrix *m2)
|
||||||
|
{
|
||||||
|
m1->right.x = m2->right.x;
|
||||||
|
m1->right.y = m2->up.x;
|
||||||
|
m1->right.z = m2->at.x;
|
||||||
|
m1->up.x = m2->right.y;
|
||||||
|
m1->up.y = m2->up.y;
|
||||||
|
m1->up.z = m2->at.y;
|
||||||
|
m1->at.x = m2->right.z;
|
||||||
|
m1->at.y = m2->up.z;
|
||||||
|
m1->at.z = m2->at.z;
|
||||||
|
m1->pos.x = -(m2->pos.x*m2->right.x +
|
||||||
|
m2->pos.y*m2->right.y +
|
||||||
|
m2->pos.z*m2->right.z);
|
||||||
|
m1->pos.y = -(m2->pos.x*m2->up.x +
|
||||||
|
m2->pos.y*m2->up.y +
|
||||||
|
m2->pos.z*m2->up.z);
|
||||||
|
m1->pos.z = -(m2->pos.x*m2->at.x +
|
||||||
|
m2->pos.y*m2->at.y +
|
||||||
|
m2->pos.z*m2->at.z);
|
||||||
|
m1->rightw = 0.0f;
|
||||||
|
m1->upw = 0.0f;
|
||||||
|
m1->atw = 0.0f;
|
||||||
|
m1->posw = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Matrix::transpose(Matrix *m1, Matrix *m2)
|
Matrix::transpose(Matrix *m1, Matrix *m2)
|
||||||
{
|
{
|
||||||
|
|
116
src/camera.cpp
116
src/camera.cpp
|
@ -17,28 +17,86 @@ defaultBeginUpdateCB(Camera *cam)
|
||||||
{
|
{
|
||||||
engine->currentCamera = cam;
|
engine->currentCamera = cam;
|
||||||
Frame::syncDirty();
|
Frame::syncDirty();
|
||||||
DRIVER->beginUpdate(cam);
|
engine->beginUpdate(cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
defaultEndUpdateCB(Camera *cam)
|
defaultEndUpdateCB(Camera *cam)
|
||||||
{
|
{
|
||||||
DRIVER->endUpdate(cam);
|
engine->endUpdate(cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cameraSync(ObjectWithFrame*)
|
cameraSync(ObjectWithFrame *obj)
|
||||||
{
|
{
|
||||||
// TODO: calculate view matrix here (i.e. projection * inverseLTM)
|
/*
|
||||||
// RW projection matrix looks like this:
|
* RW projection matrix looks like this:
|
||||||
// (cf. Camera View Matrix white paper)
|
* (cf. Camera View Matrix white paper)
|
||||||
// w = viewWindow width
|
* w = viewWindow width
|
||||||
// h = viewWindow height
|
* h = viewWindow height
|
||||||
// o = view offset
|
* o = view offset
|
||||||
//
|
*
|
||||||
// 1/2w 0 ox/2w + 1/2 -ox/2w
|
* perspective:
|
||||||
// 0 -1/2h -oy/2h + 1/2 oy/2h
|
* 1/2w 0 ox/2w + 1/2 -ox/2w
|
||||||
// 0 0 1 0
|
* 0 -1/2h -oy/2h + 1/2 oy/2h
|
||||||
|
* 0 0 1 0
|
||||||
|
* 0 0 1 0
|
||||||
|
*
|
||||||
|
* parallel:
|
||||||
|
* 1/2w 0 ox/2w -ox/2w + 1/2
|
||||||
|
* 0 -1/2h -oy/2h oy/2h + 1/2
|
||||||
|
* 0 0 1 0
|
||||||
|
* 0 0 0 1
|
||||||
|
*
|
||||||
|
* The view matrix transforms from world to clip space, it is however
|
||||||
|
* not used for OpenGL or D3D since transformation to camera space
|
||||||
|
* and to clip space are handled by separate matrices there.
|
||||||
|
* On these platforms the two matrices are built in the platform's
|
||||||
|
* beginUpdate function.
|
||||||
|
* On the PS2 the 1/2 translation/shear is removed again on the VU1.
|
||||||
|
*
|
||||||
|
* RW builds this matrix directly without using explicit
|
||||||
|
* inversion and matrix multiplication.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Camera *cam = (Camera*)obj;
|
||||||
|
Matrix inv, proj;
|
||||||
|
Matrix::invertOrthonormal(&inv, cam->getFrame()->getLTM());
|
||||||
|
float32 xscl = 2.0f/cam->viewWindow.x;
|
||||||
|
float32 yscl = 2.0f/cam->viewWindow.y;
|
||||||
|
|
||||||
|
proj.right.x = xscl;
|
||||||
|
proj.right.y = 0.0f;
|
||||||
|
proj.right.z = 0.0f;
|
||||||
|
proj.rightw = 0.0f;
|
||||||
|
|
||||||
|
proj.up.x = 0.0f;
|
||||||
|
proj.up.y = -yscl;
|
||||||
|
proj.up.z = 0.0f;
|
||||||
|
proj.upw = 0.0f;
|
||||||
|
|
||||||
|
if(cam->projection == Camera::PERSPECTIVE){
|
||||||
|
proj.pos.x = -cam->viewOffset.x*xscl;
|
||||||
|
proj.pos.y = cam->viewOffset.y*yscl;
|
||||||
|
proj.pos.z = 0.0f;
|
||||||
|
proj.posw = 0.0f;
|
||||||
|
|
||||||
|
proj.at.x = -proj.pos.x + 0.5f;
|
||||||
|
proj.at.y = -proj.pos.y + 0.5f;
|
||||||
|
proj.at.z = 1.0f;
|
||||||
|
proj.atw = 1.0f;
|
||||||
|
}else{
|
||||||
|
proj.at.x = cam->viewOffset.x*xscl;
|
||||||
|
proj.at.y = -cam->viewOffset.y*yscl;
|
||||||
|
proj.at.z = 1.0f;
|
||||||
|
proj.atw = 0.0f;
|
||||||
|
|
||||||
|
proj.pos.x = -proj.at.x + 0.5f;
|
||||||
|
proj.pos.y = -proj.at.y + 0.5f;
|
||||||
|
proj.pos.z = 0.0f;
|
||||||
|
proj.posw = 1.0f;
|
||||||
|
}
|
||||||
|
Matrix::mult(&cam->viewMatrix, &proj, &inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -127,7 +185,37 @@ Camera::destroy(void)
|
||||||
void
|
void
|
||||||
Camera::clear(RGBA *col, uint32 mode)
|
Camera::clear(RGBA *col, uint32 mode)
|
||||||
{
|
{
|
||||||
DRIVER->clearCamera(this, col, mode);
|
engine->clearCamera(this, col, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
calczShiftScale(Camera *cam)
|
||||||
|
{
|
||||||
|
float32 n = cam->nearPlane;
|
||||||
|
float32 f = cam->farPlane;
|
||||||
|
float32 N = engine->zNear;
|
||||||
|
float32 F = engine->zFar;
|
||||||
|
if(cam->projection == Camera::PERSPECTIVE){
|
||||||
|
cam->zScale = (N - F)*n*f/(f - n);
|
||||||
|
cam->zShift = (F*f - N*n)/(f - n);
|
||||||
|
}else{
|
||||||
|
cam->zScale = (F - N)/(f -n);
|
||||||
|
cam->zShift = (N*f - F*n)/(f - n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Camera::setNearPlane(float32 near)
|
||||||
|
{
|
||||||
|
this->nearPlane = near;
|
||||||
|
calczShiftScale(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Camera::setFarPlane(float32 far)
|
||||||
|
{
|
||||||
|
this->farPlane = far;
|
||||||
|
calczShiftScale(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CameraChunkData
|
struct CameraChunkData
|
||||||
|
|
|
@ -184,8 +184,7 @@ beginUpdate(Camera *cam)
|
||||||
|
|
||||||
// View Matrix
|
// View Matrix
|
||||||
Matrix inv;
|
Matrix inv;
|
||||||
// TODO: this can be simplified, or we use matrix flags....
|
Matrix::invertOrthonormal(&inv, cam->getFrame()->getLTM());
|
||||||
Matrix::invert(&inv, cam->getFrame()->getLTM());
|
|
||||||
// Since we're looking into positive Z,
|
// Since we're looking into positive Z,
|
||||||
// flip X to ge a left handed view space.
|
// flip X to ge a left handed view space.
|
||||||
view[0] = -inv.right.x;
|
view[0] = -inv.right.x;
|
||||||
|
@ -207,11 +206,10 @@ beginUpdate(Camera *cam)
|
||||||
device->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view);
|
device->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view);
|
||||||
|
|
||||||
// Projection Matrix
|
// Projection Matrix
|
||||||
float32 invwx = 1.0f/this->viewWindow.x;
|
float32 invwx = 1.0f/cam->viewWindow.x;
|
||||||
float32 invwy = 1.0f/this->viewWindow.y;
|
float32 invwy = 1.0f/cam->viewWindow.y;
|
||||||
float32 invz = 1.0f/(this->farPlane-this->nearPlane);
|
float32 invz = 1.0f/(cam->farPlane-cam->nearPlane);
|
||||||
|
|
||||||
// is this all really correct? RW code looks a bit different...
|
|
||||||
proj[0] = invwx;
|
proj[0] = invwx;
|
||||||
proj[1] = 0.0f;
|
proj[1] = 0.0f;
|
||||||
proj[2] = 0.0f;
|
proj[2] = 0.0f;
|
||||||
|
@ -222,27 +220,22 @@ beginUpdate(Camera *cam)
|
||||||
proj[6] = 0.0f;
|
proj[6] = 0.0f;
|
||||||
proj[7] = 0.0f;
|
proj[7] = 0.0f;
|
||||||
|
|
||||||
if(this->projection == PERSPECTIVE){
|
proj[8] = cam->viewOffset.x*invwx;
|
||||||
proj[8] = this->viewOffset.x*invwx;
|
proj[9] = cam->viewOffset.y*invwy;
|
||||||
proj[9] = this->viewOffset.y*invwy;
|
proj[12] = -proj[8];
|
||||||
proj[10] = this->farPlane*invz;
|
proj[13] = -proj[9];
|
||||||
|
if(cam->projection == PERSPECTIVE){
|
||||||
|
proj[10] = cam->farPlane*invz;
|
||||||
proj[11] = 1.0f;
|
proj[11] = 1.0f;
|
||||||
|
|
||||||
proj[12] = 0.0f;
|
|
||||||
proj[13] = 0.0f;
|
|
||||||
proj[14] = -this->nearPlane*proj[10];
|
|
||||||
proj[15] = 0.0f;
|
proj[15] = 0.0f;
|
||||||
}else{
|
}else{
|
||||||
proj[8] = 0.0f;
|
|
||||||
proj[9] = 0.0f;
|
|
||||||
proj[10] = invz;
|
proj[10] = invz;
|
||||||
proj[11] = 0.0f;
|
proj[11] = 0.0f;
|
||||||
|
|
||||||
proj[12] = this->viewOffset.x*invwx;
|
|
||||||
proj[13] = this->viewOffset.y*invwy;
|
|
||||||
proj[14] = -this->nearPlane*proj[10];
|
|
||||||
proj[15] = 1.0f;
|
proj[15] = 1.0f;
|
||||||
}
|
}
|
||||||
|
proj[14] = -cam->nearPlane*proj[10];
|
||||||
device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj);
|
device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,14 @@ Engine::init(void)
|
||||||
|
|
||||||
Frame::dirtyList.init();
|
Frame::dirtyList.init();
|
||||||
|
|
||||||
|
engine->beginUpdate = null::beginUpdate;
|
||||||
|
engine->endUpdate = null::endUpdate;
|
||||||
|
engine->clearCamera = null::clearCamera;
|
||||||
|
engine->setRenderState = null::setRenderState;
|
||||||
|
engine->getRenderState = null::getRenderState;
|
||||||
|
engine->zNear = 0.0f; // random values
|
||||||
|
engine->zFar = 1.0f;
|
||||||
|
|
||||||
ps2::initializePlatform();
|
ps2::initializePlatform();
|
||||||
xbox::initializePlatform();
|
xbox::initializePlatform();
|
||||||
d3d8::initializePlatform();
|
d3d8::initializePlatform();
|
||||||
|
@ -50,12 +58,6 @@ Driver::open(void)
|
||||||
|
|
||||||
driver[i]->defaultPipeline = defpipe;
|
driver[i]->defaultPipeline = defpipe;
|
||||||
|
|
||||||
driver[i]->beginUpdate = null::beginUpdate;
|
|
||||||
driver[i]->endUpdate = null::endUpdate;
|
|
||||||
|
|
||||||
driver[i]->setRenderState = null::setRenderState;
|
|
||||||
driver[i]->getRenderState = null::getRenderState;
|
|
||||||
|
|
||||||
driver[i]->rasterCreate = null::rasterCreate;
|
driver[i]->rasterCreate = null::rasterCreate;
|
||||||
driver[i]->rasterLock = null::rasterLock;
|
driver[i]->rasterLock = null::rasterLock;
|
||||||
driver[i]->rasterUnlock = null::rasterUnlock;
|
driver[i]->rasterUnlock = null::rasterUnlock;
|
||||||
|
|
|
@ -344,8 +344,8 @@ beginUpdate(Camera *cam)
|
||||||
float view[16], proj[16];
|
float view[16], proj[16];
|
||||||
// View Matrix
|
// View Matrix
|
||||||
Matrix inv;
|
Matrix inv;
|
||||||
// TODO: this can be simplified, or we use matrix flags....
|
// TODO: maybe use matrix flags....
|
||||||
Matrix::invert(&inv, cam->getFrame()->getLTM());
|
Matrix::invertOrthonormal(&inv, cam->getFrame()->getLTM());
|
||||||
// Since we're looking into positive Z,
|
// Since we're looking into positive Z,
|
||||||
// flip X to ge a left handed view space.
|
// flip X to ge a left handed view space.
|
||||||
view[0] = -inv.right.x;
|
view[0] = -inv.right.x;
|
||||||
|
@ -381,18 +381,22 @@ beginUpdate(Camera *cam)
|
||||||
proj[6] = 0.0f;
|
proj[6] = 0.0f;
|
||||||
proj[7] = 0.0f;
|
proj[7] = 0.0f;
|
||||||
|
|
||||||
|
proj[8] = cam->viewOffset.x*invwx;
|
||||||
|
proj[9] = cam->viewOffset.y*invwy;
|
||||||
|
proj[12] = -proj[8];
|
||||||
|
proj[13] = -proj[9];
|
||||||
if(cam->projection == Camera::PERSPECTIVE){
|
if(cam->projection == Camera::PERSPECTIVE){
|
||||||
proj[8] = cam->viewOffset.x*invwx;
|
|
||||||
proj[9] = cam->viewOffset.y*invwy;
|
|
||||||
proj[10] = (cam->farPlane+cam->nearPlane)*invz;
|
proj[10] = (cam->farPlane+cam->nearPlane)*invz;
|
||||||
proj[11] = 1.0f;
|
proj[11] = 1.0f;
|
||||||
|
|
||||||
proj[12] = 0.0f;
|
|
||||||
proj[13] = 0.0f;
|
|
||||||
proj[14] = -2.0f*cam->nearPlane*cam->farPlane*invz;
|
proj[14] = -2.0f*cam->nearPlane*cam->farPlane*invz;
|
||||||
proj[15] = 0.0f;
|
proj[15] = 0.0f;
|
||||||
}else{
|
}else{
|
||||||
// TODO
|
proj[10] = -(cam->farPlane+cam->nearPlane)*invz;
|
||||||
|
proj[11] = 0.0f;
|
||||||
|
|
||||||
|
proj[14] = -2.0f*invz;
|
||||||
|
proj[15] = 1.0f;
|
||||||
}
|
}
|
||||||
setProjectionMatrix(proj);
|
setProjectionMatrix(proj);
|
||||||
|
|
||||||
|
@ -409,10 +413,12 @@ beginUpdate(Camera *cam)
|
||||||
void
|
void
|
||||||
initializeRender(void)
|
initializeRender(void)
|
||||||
{
|
{
|
||||||
driver[PLATFORM_GL3]->beginUpdate = beginUpdate;
|
engine->beginUpdate = beginUpdate;
|
||||||
driver[PLATFORM_GL3]->clearCamera = clearCamera;
|
engine->clearCamera = clearCamera;
|
||||||
driver[PLATFORM_GL3]->setRenderState = setRenderState;
|
engine->setRenderState = setRenderState;
|
||||||
driver[PLATFORM_GL3]->getRenderState = getRenderState;
|
engine->getRenderState = getRenderState;
|
||||||
|
engine->zNear = -1.0f;
|
||||||
|
engine->zFar = 1.0f;
|
||||||
|
|
||||||
simpleShader = Shader::fromFiles("simple.vert", "simple.frag");
|
simpleShader = Shader::fromFiles("simple.vert", "simple.frag");
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,7 @@ struct Matrix
|
||||||
// not very pretty :/
|
// not very pretty :/
|
||||||
static void mult(Matrix *m1, Matrix *m2, Matrix *m3);
|
static void mult(Matrix *m1, Matrix *m2, Matrix *m3);
|
||||||
static bool32 invert(Matrix *m1, Matrix *m2);
|
static bool32 invert(Matrix *m1, Matrix *m2);
|
||||||
|
static void invertOrthonormal(Matrix *m1, Matrix *m2);
|
||||||
static void transpose(Matrix *m1, Matrix *m2);
|
static void transpose(Matrix *m1, Matrix *m2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -43,31 +43,34 @@ enum BlendFunction
|
||||||
// TODO: add more perhaps
|
// TODO: add more perhaps
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is for platform independent things
|
// This is for platform independent things and the render device (of which
|
||||||
|
// there can only ever be one).
|
||||||
// TODO: move more stuff into this
|
// TODO: move more stuff into this
|
||||||
struct Engine
|
struct Engine
|
||||||
{
|
{
|
||||||
void *currentCamera;
|
void *currentCamera;
|
||||||
void *currentWorld;
|
void *currentWorld;
|
||||||
|
|
||||||
|
// Device
|
||||||
|
float32 zNear, zFar;
|
||||||
|
void (*beginUpdate)(Camera*);
|
||||||
|
void (*endUpdate)(Camera*);
|
||||||
|
void (*clearCamera)(Camera*, RGBA *col, uint32 mode);
|
||||||
|
void (*setRenderState)(int32 state, uint32 value);
|
||||||
|
uint32 (*getRenderState)(int32 state);
|
||||||
|
|
||||||
static void init(void);
|
static void init(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Engine *engine;
|
extern Engine *engine;
|
||||||
|
|
||||||
// This is for platform driver implementations
|
// This is for platform driver implementations which have to be available
|
||||||
|
// regardless of the render device.
|
||||||
struct Driver
|
struct Driver
|
||||||
{
|
{
|
||||||
ObjPipeline *defaultPipeline;
|
ObjPipeline *defaultPipeline;
|
||||||
int32 rasterNativeOffset;
|
int32 rasterNativeOffset;
|
||||||
|
|
||||||
void (*beginUpdate)(Camera*);
|
|
||||||
void (*endUpdate)(Camera*);
|
|
||||||
void (*clearCamera)(Camera*, RGBA *col, uint32 mode);
|
|
||||||
|
|
||||||
void (*setRenderState)(int32 state, uint32 value);
|
|
||||||
uint32 (*getRenderState)(int32 state);
|
|
||||||
|
|
||||||
void (*rasterCreate)(Raster*);
|
void (*rasterCreate)(Raster*);
|
||||||
uint8 *(*rasterLock)(Raster*, int32 level);
|
uint8 *(*rasterLock)(Raster*, int32 level);
|
||||||
void (*rasterUnlock)(Raster*, int32 level);
|
void (*rasterUnlock)(Raster*, int32 level);
|
||||||
|
@ -87,10 +90,10 @@ extern Driver *driver[NUM_PLATFORMS];
|
||||||
#define DRIVER driver[rw::platform]
|
#define DRIVER driver[rw::platform]
|
||||||
|
|
||||||
inline void setRenderState(int32 state, uint32 value){
|
inline void setRenderState(int32 state, uint32 value){
|
||||||
DRIVER->setRenderState(state, value); }
|
engine->setRenderState(state, value); }
|
||||||
|
|
||||||
inline uint32 getRenderState(int32 state){
|
inline uint32 getRenderState(int32 state){
|
||||||
return DRIVER->getRenderState(state); }
|
return engine->getRenderState(state); }
|
||||||
|
|
||||||
namespace null {
|
namespace null {
|
||||||
void beginUpdate(Camera*);
|
void beginUpdate(Camera*);
|
||||||
|
|
|
@ -535,6 +535,9 @@ struct Camera : PluginBase<Camera>
|
||||||
float32 fogPlane;
|
float32 fogPlane;
|
||||||
int32 projection;
|
int32 projection;
|
||||||
|
|
||||||
|
Matrix viewMatrix;
|
||||||
|
float32 zScale, zShift;
|
||||||
|
|
||||||
// clump link handled by plugin in RW
|
// clump link handled by plugin in RW
|
||||||
Clump *clump;
|
Clump *clump;
|
||||||
LLLink inClump;
|
LLLink inClump;
|
||||||
|
@ -556,6 +559,8 @@ struct Camera : PluginBase<Camera>
|
||||||
void beginUpdate(void) { this->beginUpdateCB(this); }
|
void beginUpdate(void) { this->beginUpdateCB(this); }
|
||||||
void endUpdate(void) { this->endUpdateCB(this); }
|
void endUpdate(void) { this->endUpdateCB(this); }
|
||||||
void clear(RGBA *col, uint32 mode);
|
void clear(RGBA *col, uint32 mode);
|
||||||
|
void setNearPlane(float32);
|
||||||
|
void setFarPlane(float32);
|
||||||
static Camera *streamRead(Stream *stream);
|
static Camera *streamRead(Stream *stream);
|
||||||
bool streamWrite(Stream *stream);
|
bool streamWrite(Stream *stream);
|
||||||
uint32 streamGetSize(void);
|
uint32 streamGetSize(void);
|
||||||
|
|
Loading…
Reference in New Issue