From cc77487fc00e42d63994660318e5f968246a0e58 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 14 Feb 2016 20:56:05 +0100 Subject: [PATCH] implemented projection in Camera --- src/clump.cpp | 143 ++++++++++++++++++++++++++++++------------------ src/d3d8.cpp | 18 ++++++ src/rwbase.cpp | 65 ++++++++++++++++++++++ src/rwbase.h | 95 +++++++++++++++++++++++++++++--- src/rwd3d8.h | 5 ++ src/rwobjects.h | 50 ++++++----------- 6 files changed, 282 insertions(+), 94 deletions(-) diff --git a/src/clump.cpp b/src/clump.cpp index 925ebc1..793d9d2 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -30,12 +30,8 @@ Frame::create(void) f->child = NULL; f->next = NULL; f->root = f; - for(int i = 0; i < 16; i++) - f->matrix[i] = 0.0f; - f->matrix[0] = 1.0f; - f->matrix[5] = 1.0f; - f->matrix[10] = 1.0f; - f->matrix[15] = 1.0f; + f->matrix.setIdentity(); + f->ltm.setIdentity(); f->constructPlugins(); return f; } @@ -166,7 +162,7 @@ syncRecurse(Frame *frame, uint8 flags) for(; frame; frame = frame->next){ flg = flags | frame->object.privateFlags; if(flg & Frame::SUBTREESYNCLTM){ - matrixMult(frame->ltm, frame->getParent()->ltm, frame->matrix); + Matrix::mult(&frame->ltm, &frame->getParent()->ltm, &frame->matrix); frame->object.privateFlags &= ~Frame::SUBTREESYNCLTM; } syncRecurse(frame->child, flg); @@ -179,11 +175,11 @@ Frame::syncHierarchyLTM(void) Frame *child; uint8 flg; if(this->object.privateFlags & Frame::SUBTREESYNCLTM) - memcpy(this->ltm, this->matrix, 64); + this->ltm = this->matrix; for(child = this->child; child; child = child->next){ flg = this->object.privateFlags | child->object.privateFlags; if(flg & Frame::SUBTREESYNCLTM){ - matrixMult(child->ltm, this->ltm, child->matrix); + Matrix::mult(&child->ltm, &this->ltm, &child->matrix); child->object.privateFlags &= ~Frame::SUBTREESYNCLTM; } syncRecurse(child, flg); @@ -191,12 +187,12 @@ Frame::syncHierarchyLTM(void) this->object.privateFlags &= ~Frame::SYNCLTM; } -float* +Matrix* Frame::getLTM(void) { if(this->root->object.privateFlags & Frame::HIERARCHYSYNCLTM) this->root->syncHierarchyLTM(); - return this->ltm; + return &this->ltm; } void @@ -224,7 +220,8 @@ Frame::cloneAndLink(Frame *clonedroot) if(clonedroot == NULL) clonedroot = frame; frame->object.copy(&this->object); - memcpy(frame->matrix, this->matrix, sizeof(this->matrix)); + 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){ @@ -447,8 +444,7 @@ Clump::streamWrite(Stream *stream) struct FrameStreamData { - float32 mat[9]; - float32 pos[3]; + V3d right, up, at, pos; int32 parent; int32 matflag; }; @@ -490,6 +486,16 @@ Clump::streamGetSize(void) return size; } +void +Clump::render(void) +{ + Atomic *a; + FORLIST(lnk, this->atomics){ + a = Atomic::fromClump(lnk); + if(a->object.flags & Atomic::RENDER) + a->render(); + } +} void Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf) @@ -504,22 +510,14 @@ Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf) Frame *f; frameList[i] = f = Frame::create(); stream->read(&buf, sizeof(buf)); - f->matrix[0] = buf.mat[0]; - f->matrix[1] = buf.mat[1]; - f->matrix[2] = buf.mat[2]; - f->matrix[3] = 0.0f; - f->matrix[4] = buf.mat[3]; - f->matrix[5] = buf.mat[4]; - f->matrix[6] = buf.mat[5]; - f->matrix[7] = 0.0f; - f->matrix[8] = buf.mat[6]; - f->matrix[9] = buf.mat[7]; - f->matrix[10] = buf.mat[8]; - f->matrix[11] = 0.0f; - f->matrix[12] = buf.pos[0]; - f->matrix[13] = buf.pos[1]; - f->matrix[14] = buf.pos[2]; - f->matrix[15] = 1.0f; + 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; //f->matflag = buf.matflag; if(buf.parent >= 0) frameList[buf.parent]->addChild(f); @@ -546,18 +544,10 @@ Clump::frameListStreamWrite(Stream *stream, Frame **frameList, int32 numFrames) stream->writeU32(numFrames); for(int32 i = 0; i < numFrames; i++){ Frame *f = frameList[i]; - buf.mat[0] = f->matrix[0]; - buf.mat[1] = f->matrix[1]; - buf.mat[2] = f->matrix[2]; - buf.mat[3] = f->matrix[4]; - buf.mat[4] = f->matrix[5]; - buf.mat[5] = f->matrix[6]; - buf.mat[6] = f->matrix[8]; - buf.mat[7] = f->matrix[9]; - buf.mat[8] = f->matrix[10]; - buf.pos[0] = f->matrix[12]; - buf.pos[1] = f->matrix[13]; - buf.pos[2] = f->matrix[14]; + buf.right = f->matrix.right; + buf.up = f->matrix.up; + buf.at = f->matrix.at; + buf.pos = f->matrix.pos; buf.parent = findPointer(f->getParent(), (void**)frameList, numFrames); buf.matflag = 0; //f->matflag; @@ -580,17 +570,9 @@ Atomic::create(void) atomic->geometry = NULL; atomic->pipeline = NULL; atomic->renderCB = Atomic::defaultRenderCB; + atomic->object.flags = Atomic::COLLISIONTEST | Atomic::RENDER; atomic->constructPlugins(); - // flags: - // rpATOMICCOLLISIONTEST = 0x01, /**geometry = Geometry::streamRead(stream); }else atomic->geometry = geometryList[buf[1]]; + atomic->object.flags = buf[2]; atomicRights[0] = 0; atomic->streamReadPlugins(stream); @@ -649,7 +632,7 @@ Atomic::streamReadClump(Stream *stream, bool Atomic::streamWriteClump(Stream *stream, Frame **frameList, int32 numFrames) { - int32 buf[4] = { 0, 0, 5, 0 }; + int32 buf[4] = { 0, 0, 0, 0 }; Clump *c = this->clump; if(c == NULL) return false; @@ -658,6 +641,7 @@ Atomic::streamWriteClump(Stream *stream, Frame **frameList, int32 numFrames) buf[0] = findPointer(this->getFrame(), (void**)frameList, numFrames); if(version < 0x30400){ + buf[1] = this->object.flags; stream->write(buf, sizeof(int[3])); this->geometry->streamWrite(stream); }else{ @@ -669,6 +653,7 @@ Atomic::streamWriteClump(Stream *stream, Frame **frameList, int32 numFrames) } return false; foundgeo: + buf[2] = this->object.flags; stream->write(buf, sizeof(buf)); } @@ -864,7 +849,7 @@ Camera::create(void) cam->nearPlane = 0.05f; cam->farPlane = 10.0f; cam->fogPlane = 5.0f; - cam->projection = 1; + cam->projection = Camera::PERSPECTIVE; cam->constructPlugins(); return cam; } @@ -942,4 +927,56 @@ 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); +} + } diff --git a/src/d3d8.cpp b/src/d3d8.cpp index fafdbfd..a8c1a01 100644 --- a/src/d3d8.cpp +++ b/src/d3d8.cpp @@ -276,13 +276,28 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) destroyNativeData(geo, 0, 0); } +static void +render(rw::ObjPipeline *rwpipe, Atomic *atomic) +{ + ObjPipeline *pipe = (ObjPipeline*)rwpipe; + Geometry *geo = atomic->geometry; + if((geo->geoflags & Geometry::NATIVE) == 0) + pipe->instance(atomic); + assert(geo->instData != NULL); + assert(geo->instData->platform == PLATFORM_D3D8); + if(pipe->renderCB) + pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData); +} + ObjPipeline::ObjPipeline(uint32 platform) : rw::ObjPipeline(platform) { this->impl.instance = d3d8::instance; this->impl.uninstance = d3d8::uninstance; + this->impl.render = d3d8::render; this->instanceCB = NULL; this->uninstanceCB = NULL; + this->renderCB = NULL; } void @@ -360,6 +375,7 @@ makeDefaultPipeline(void) ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); pipe->instanceCB = defaultInstanceCB; pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; return pipe; } @@ -369,6 +385,7 @@ makeSkinPipeline(void) ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); pipe->instanceCB = defaultInstanceCB; pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; pipe->pluginID = ID_SKIN; pipe->pluginData = 1; return pipe; @@ -380,6 +397,7 @@ makeMatFXPipeline(void) ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); pipe->instanceCB = defaultInstanceCB; pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; pipe->pluginID = ID_MATFX; pipe->pluginData = 0; return pipe; diff --git a/src/rwbase.cpp b/src/rwbase.cpp index 9314606..453309b 100644 --- a/src/rwbase.cpp +++ b/src/rwbase.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "rwbase.h" #include "rwplugin.h" @@ -30,6 +31,8 @@ int32 build = 0xFFFF; #endif char *debugFile = NULL; +static Matrix identMat; + void initialize(void) { @@ -49,6 +52,55 @@ initialize(void) d3d9::makeDefaultPipeline(); Frame::dirtyList.init(); + + identMat.right.set(1.0f, 0.0f, 0.0f); + identMat.rightw = 0.0f; + identMat.up.set(0.0f, 1.0f, 0.0f); + identMat.upw = 0.0f; + identMat.at.set(0.0f, 0.0f, 1.0f); + identMat.atw = 0.0f; + identMat.pos.set(0.0f, 0.0f, 0.0f); + identMat.posw = 1.0f; +} + +float32 +V3d::length(void) +{ + return sqrt(this->x*this->x+this->y*this->y+this->z*this->z); +} + +V3d +V3d::normalize(void) +{ + return V3d::scale(this, 1.0f/this->length()); +} + +V3d +V3d::cross(V3d *a, V3d *b) +{ + V3d res; + res.x = a->y*b->z - a->z*b->y; + res.y = a->z*b->x - a->x*b->z; + res.z = a->x*b->y - a->y*b->x; + return res; +} + +void +Matrix::setIdentity(void) +{ + *this = identMat; +} + +void +Matrix::mult(Matrix *m1, Matrix *m2, Matrix *m3) +{ + matrixMult((float32*)m1, (float32*)m2, (float32*)m3); +} + +void +Matrix::invert(Matrix *m1, Matrix *m2) +{ + matrixInvert((float32*)m1, (float32*)m2); } void @@ -232,6 +284,19 @@ matrixInvert(float32 *out, float32 *m) out[i] = inv[i] * det; } +void +matrixPrint(float32 *mat) +{ + printf("[ [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" + " [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" + " [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" + " [ %8.4f, %8.4f, %8.4f, %8.4f ] ]\n", + mat[0], mat[4], mat[8], mat[12], + mat[1], mat[5], mat[9], mat[13], + mat[2], mat[6], mat[10], mat[14], + mat[3], mat[7], mat[11], mat[15]); +} + int32 Stream::writeI8(int8 val) { diff --git a/src/rwbase.h b/src/rwbase.h index 44977a3..207e81e 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -34,6 +34,93 @@ typedef uint32 uint; #define nelem(A) (sizeof(A) / sizeof A[0]) +struct RGBA +{ + uint8 red; + uint8 green; + uint8 blue; + uint8 alpha; +}; + +struct RGBAf +{ + float32 red; + float32 green; + float32 blue; + float32 alpha; +}; + +struct V2d +{ + float32 x, y; + void set(float32 x, float32 y){ + this->x = x; this->y = y; } +}; + +struct V3d +{ + float32 x, y, z; + void set(float32 x, float32 y, float32 z){ + this->x = x; this->y = y; this->z = z; } + static V3d sub(V3d *a, V3d *b){ + V3d res; + res.x = a->x - b->x; + res.y = a->y - b->y; + res.z = a->z - b->z; + return res; + } + static V3d add(V3d *a, V3d *b){ + V3d res; + res.x = a->x + b->x; + res.y = a->y + b->y; + res.z = a->z + b->z; + return res; + } + static V3d scale(V3d *a, float32 r){ + V3d res; + res.x = a->x*r; + res.y = a->y*r; + res.z = a->z*r; + return res; + } + float32 length(void); + V3d normalize(void); + static V3d cross(V3d *a, V3d *b); +}; + +struct Quat +{ + float32 w, x, y, z; + void set(float32 w, float32 x, float32 y, float32 z){ + this->w = w; this->x = x; this->y = y; this->z = z; } +}; + +struct Matrix +{ + V3d right; + float32 rightw; + V3d up; + float32 upw; + V3d at; + float32 atw; + V3d pos; + float32 posw; + + void setIdentity(void); + // not very pretty :/ + static void mult(Matrix *m1, Matrix *m2, Matrix *m3); + static void invert(Matrix *m1, Matrix *m2); +}; + +void matrixIdentity(float32 *mat); +int matrixEqual(float32 *m1, float32 *m2); +int matrixIsIdentity(float32 *mat); +void matrixMult(float32 *out, float32 *a, float32 *b); +void vecTrans(float32 *out, float32 *mat, float32 *vec); +void matrixTranspose(float32 *out, float32 *in); +void matrixInvert(float32 *out, float32 *in); +void matrixPrint(float32 *mat); + class Stream { public: @@ -155,14 +242,6 @@ extern char *debugFile; void initialize(void); -void matrixIdentity(float32 *mat); -int matrixEqual(float32 *m1, float32 *m2); -int matrixIsIdentity(float32 *mat); -void matrixMult(float32 *out, float32 *a, float32 *b); -void vecTrans(float32 *out, float32 *mat, float32 *vec); -void matrixTranspose(float32 *out, float32 *in); -void matrixInvert(float32 *out, float32 *in); - // 0x04000000 3.1 // 0x08000000 3.2 // 0x0C000000 3.3 diff --git a/src/rwd3d8.h b/src/rwd3d8.h index f57bad5..a3b1428 100644 --- a/src/rwd3d8.h +++ b/src/rwd3d8.h @@ -40,10 +40,15 @@ class ObjPipeline : public rw::ObjPipeline public: void (*instanceCB)(Geometry *geo, InstanceData *header); void (*uninstanceCB)(Geometry *geo, InstanceData *header); + void (*renderCB)(Atomic *atomic, InstanceDataHeader *header); ObjPipeline(uint32 platform); }; +void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header); +void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header); +void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header); + ObjPipeline *makeDefaultPipeline(void); ObjPipeline *makeSkinPipeline(void); diff --git a/src/rwobjects.h b/src/rwobjects.h index f9c942f..dd278bf 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -2,36 +2,6 @@ namespace rw { -struct RGBA -{ - uint8 red; - uint8 green; - uint8 blue; - uint8 alpha; -}; - -struct RGBAf -{ - float32 red; - float32 green; - float32 blue; - float32 alpha; -}; - -struct V2d -{ - float32 x, y; - void set(float32 x, float32 y){ - this->x = x; this->y = y; } -}; - -struct V3d -{ - float32 x, y, z; - void set(float32 x, float32 y, float32 z){ - this->x = x; this->y = y; this->z = z; } -}; - struct LLLink { LLLink *next; @@ -130,8 +100,10 @@ struct Frame : PluginBase Object object; LLLink inDirtyList; LinkList objectList; - float32 matrix[16]; - float32 ltm[16]; + Matrix matrix; + Matrix ltm; + //float32 matrix[16]; + //float32 ltm[16]; Frame *child; Frame *next; @@ -149,7 +121,7 @@ struct Frame : PluginBase Frame *getParent(void){ return (Frame*)this->object.parent; } int32 count(void); - float *getLTM(void); + Matrix *getLTM(void); void updateObjects(void); void syncHierarchyLTM(void); @@ -590,6 +562,10 @@ struct Atomic : PluginBase { typedef void (*RenderCB)(Atomic *atomic); enum { ID = 1 }; + enum { + COLLISIONTEST = 0x01, // unused here + RENDER = 0x04 + }; ObjectWithFrame object; Geometry *geometry; @@ -662,12 +638,15 @@ struct Light : PluginBase struct Camera : PluginBase { enum { ID = 4 }; + enum { PERSPECTIVE = 1, PARALLEL }; + ObjectWithFrame object; V2d viewWindow; V2d viewOffset; float32 nearPlane, farPlane; float32 fogPlane; int32 projection; + float32 projMat[16]; Clump *clump; LLLink inClump; @@ -682,6 +661,10 @@ struct Camera : PluginBase static Camera *streamRead(Stream *stream); bool streamWrite(Stream *stream); uint32 streamGetSize(void); + + void updateProjectionMatrix(void); + // fov in degrees + void setFOV(float32 fov, float32 ratio); }; struct Clump : PluginBase @@ -717,6 +700,7 @@ struct Clump : PluginBase static Clump *streamRead(Stream *stream); bool streamWrite(Stream *stream); uint32 streamGetSize(void); + void render(void); void frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf); void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf);