diff --git a/TODO b/TODO index b66a1fb..5c2c220 100644 --- a/TODO +++ b/TODO @@ -2,9 +2,7 @@ TODO: - tristrips - examples skeleton + interface - camera camtex - subrast matfx1 (more new shaders) hanim1 fog diff --git a/premake5.lua b/premake5.lua index 141432e..e635c1b 100755 --- a/premake5.lua +++ b/premake5.lua @@ -217,6 +217,14 @@ project "subrast" removeplatforms { "*null" } removeplatforms { "ps2" } +project "camera" + kind "WindowedApp" + characterset ("MBCS") + skeltool("camera") + flags { "WinMain" } + removeplatforms { "*null" } + removeplatforms { "ps2" } + project "ska2anm" kind "ConsoleApp" characterset ("MBCS") diff --git a/skeleton/skeleton.cpp b/skeleton/skeleton.cpp index 3defebe..e6871e8 100644 --- a/skeleton/skeleton.cpp +++ b/skeleton/skeleton.cpp @@ -95,7 +95,7 @@ CameraDestroy(rw::Camera *cam) } void -CameraSize(Camera *cam, Rect *r) +CameraSize(Camera *cam, Rect *r, float viewWindow, float aspectRatio) { if(cam->frameBuffer){ cam->frameBuffer->destroy(); @@ -107,6 +107,60 @@ CameraSize(Camera *cam, Rect *r) } cam->frameBuffer = Raster::create(r->w, r->h, 0, Raster::CAMERA); cam->zBuffer = Raster::create(r->w, r->h, 0, Raster::ZBUFFER); + + if(viewWindow != 0.0f){ + rw::V2d vw; + // TODO: aspect ratio when fullscreen + if(r->w > r->h){ + vw.x = viewWindow; + vw.y = viewWindow / ((float)r->w/r->h); + }else{ + vw.x = viewWindow / ((float)r->h/r->w); + vw.y = viewWindow; + } + cam->setViewWindow(&vw); + } +} + +void +CameraMove(Camera *cam, V3d *delta) +{ + rw::V3d offset; + rw::V3d::transformVectors(&offset, delta, 1, &cam->getFrame()->matrix); + cam->getFrame()->translate(&offset); +} + +void +CameraPan(Camera *cam, V3d *pos, float angle) +{ + rw::Frame *frame = cam->getFrame(); + rw::V3d trans = pos ? *pos : frame->matrix.pos; + rw::V3d negTrans = rw::scale(trans, -1.0f); + frame->translate(&negTrans); + frame->rotate(&frame->matrix.up, angle); + frame->translate(&trans); +} + +void +CameraTilt(Camera *cam, V3d *pos, float angle) +{ + rw::Frame *frame = cam->getFrame(); + rw::V3d trans = pos ? *pos : frame->matrix.pos; + rw::V3d negTrans = rw::scale(trans, -1.0f); + frame->translate(&negTrans); + frame->rotate(&frame->matrix.right, angle); + frame->translate(&trans); +} + +void +CameraRotate(Camera *cam, V3d *pos, float angle) +{ + rw::Frame *frame = cam->getFrame(); + rw::V3d trans = pos ? *pos : frame->matrix.pos; + rw::V3d negTrans = rw::scale(trans, -1.0f); + frame->translate(&negTrans); + frame->rotate(&frame->matrix.at, angle); + frame->translate(&negTrans); } EventStatus diff --git a/skeleton/skeleton.h b/skeleton/skeleton.h index b802718..00602e2 100644 --- a/skeleton/skeleton.h +++ b/skeleton/skeleton.h @@ -104,7 +104,11 @@ bool InitRW(void); void TerminateRW(void); Camera *CameraCreate(int32 width, int32 height, bool32 z); void CameraDestroy(rw::Camera *cam); -void CameraSize(Camera *cam, Rect *r); +void CameraSize(Camera *cam, Rect *r, float viewWindow = 0.0f, float aspectRatio = 0.0f); +void CameraMove(Camera *cam, V3d *delta); +void CameraPan(Camera *cam, V3d *pos, float angle); +void CameraTilt(Camera *cam, V3d *pos, float angle); +void CameraRotate(Camera *cam, V3d *pos, float angle); void SetMousePosition(int x, int y); EventStatus EventHandler(Event e, void *param); diff --git a/src/rwbase.h b/src/rwbase.h index dc0b1cc..13891ca 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -278,7 +278,7 @@ struct Quat this->w = w; this->x = x; this->y = y; this->z = z; } V3d vec(void){ return makeV3d(x, y, z); } - Quat *rotate(const V3d *axis, float32 angle, CombineOp op); + Quat *rotate(const V3d *axis, float32 angle, CombineOp op = rw::COMBINEPOSTCONCAT); }; inline Quat makeQuat(float32 w, float32 x, float32 y, float32 z) { Quat q = { x, y, z, w }; return q; } @@ -347,11 +347,11 @@ struct Matrix static Matrix *mult(Matrix *dst, const Matrix *src1, const Matrix *src2); static Matrix *invert(Matrix *dst, const Matrix *src); static Matrix *transpose(Matrix *dst, const Matrix *src); - Matrix *rotate(const V3d *axis, float32 angle, CombineOp op); - Matrix *rotate(const Quat &q, CombineOp op); - Matrix *translate(const V3d *translation, CombineOp op); - Matrix *scale(const V3d *scl, CombineOp op); - Matrix *transform(const Matrix *mat, CombineOp op); + Matrix *rotate(const V3d *axis, float32 angle, CombineOp op = rw::COMBINEPOSTCONCAT); + Matrix *rotate(const Quat &q, CombineOp op = rw::COMBINEPOSTCONCAT); + Matrix *translate(const V3d *translation, CombineOp op = rw::COMBINEPOSTCONCAT); + Matrix *scale(const V3d *scl, CombineOp op = rw::COMBINEPOSTCONCAT); + Matrix *transform(const Matrix *mat, CombineOp op = rw::COMBINEPOSTCONCAT); Quat getRotation(void); void lookAt(const V3d &dir, const V3d &up); diff --git a/src/rwobjects.h b/src/rwobjects.h index 3ecf14f..5cd833f 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -70,10 +70,10 @@ struct Frame bool32 dirty(void) const { return !!(this->root->object.privateFlags & HIERARCHYSYNC); } Matrix *getLTM(void); - void rotate(const V3d *axis, float32 angle, CombineOp op); - void translate(const V3d *trans, CombineOp op); - void scale(const V3d *scale, CombineOp op); - void transform(const Matrix *mat, CombineOp op); + void rotate(const V3d *axis, float32 angle, CombineOp op = rw::COMBINEPOSTCONCAT); + void translate(const V3d *trans, CombineOp op = rw::COMBINEPOSTCONCAT); + void scale(const V3d *scale, CombineOp op = rw::COMBINEPOSTCONCAT); + void transform(const Matrix *mat, CombineOp op = rw::COMBINEPOSTCONCAT); void updateObjects(void); diff --git a/tools/camera/camexamp.cpp b/tools/camera/camexamp.cpp new file mode 100644 index 0000000..5f072c6 --- /dev/null +++ b/tools/camera/camexamp.cpp @@ -0,0 +1,395 @@ +#include +#include + +#include "viewer.h" +#include "camexamp.h" + +#define TEXSIZE 256 + +rw::Camera *MainCamera; +rw::Camera *SubCamera; + +rw::Raster *SubCameraRaster; +rw::Raster *SubCameraZRaster; +rw::Raster *SubCameraMainCameraSubRaster; +rw::Raster *SubCameraMainCameraSubZRaster; + +TextureCamera CameraTexture; + +rw::int32 CameraSelected = 0; +rw::int32 ProjectionIndex = 0; +bool SubCameraMiniView = true; + +CameraData SubCameraData; + +void +CameraQueryData(CameraData *data, CameraDataType type, rw::Camera *camera) +{ + data->camera = camera; + if(type & FARCLIPPLANE) data->farClipPlane = camera->farPlane; + if(type & NEARCLIPPLANE) data->nearClipPlane = camera->nearPlane; + if(type & PROJECTION) data->projection = camera->projection; + if(type & OFFSET) data->offset = camera->viewOffset; + if(type & VIEWWINDOW) data->viewWindow = camera->viewWindow; + if(type & MATRIX) data->matrix = &camera->getFrame()->matrix; +} + +void +CameraSetData(CameraData *data, CameraDataType type) +{ + if(type & FARCLIPPLANE) data->camera->setFarPlane(data->farClipPlane); + if(type & NEARCLIPPLANE) data->camera->setNearPlane(data->nearClipPlane); + if(type & PROJECTION) data->camera->setProjection(data->projection); + if(type & OFFSET) data->camera->setViewOffset(&data->offset); + if(type & VIEWWINDOW) data->camera->setViewWindow(&data->viewWindow); +} + +void +ProjectionCallback(void) +{ + if(ProjectionIndex == 0) + SubCameraData.projection = rw::Camera::PERSPECTIVE; + else + SubCameraData.projection = rw::Camera::PARALLEL; + CameraSetData(&SubCameraData, PROJECTION); +} + +void +ClipPlaneCallback(void) +{ + CameraSetData(&SubCameraData, (CameraDataType)(NEARCLIPPLANE | FARCLIPPLANE)); +} + +void +ChangeViewOffset(float deltaX, float deltaY) +{ + SubCameraData.offset.x += deltaX; + SubCameraData.offset.y += deltaY; + if(SubCameraData.offset.x > 5.0f) + SubCameraData.offset.x = 5.0f; + if(SubCameraData.offset.x < -5.0f) + SubCameraData.offset.x = -5.0f; + if(SubCameraData.offset.y > 5.0f) + SubCameraData.offset.y = 5.0f; + if(SubCameraData.offset.y < -5.0f) + SubCameraData.offset.y = -5.0f; + CameraSetData(&SubCameraData, OFFSET); +} + +void +ChangeViewWindow(float deltaX, float deltaY) +{ + SubCameraData.viewWindow.x += deltaX; + SubCameraData.viewWindow.y += deltaY; + if(SubCameraData.viewWindow.x > 5.0f) + SubCameraData.viewWindow.x = 5.0f; + if(SubCameraData.viewWindow.x < 0.01f) + SubCameraData.viewWindow.x = 0.01f; + if(SubCameraData.viewWindow.y > 5.0f) + SubCameraData.viewWindow.y = 5.0f; + if(SubCameraData.viewWindow.y < 0.01f) + SubCameraData.viewWindow.y = 0.01f; + CameraSetData(&SubCameraData, VIEWWINDOW); +} + +void +CamerasCreate(rw::World *world) +{ + rw::V3d offset = { 3.0f, 0.0f, 8.0f }; + float rotate = -90.0f; + + SubCamera = ViewerCreate(world); + ViewerMove(SubCamera, &offset); + ViewerRotate(SubCamera, rotate, 0.0f); + + MainCamera = ViewerCreate(world); + + CameraQueryData(&SubCameraData, ALL, SubCamera); + + SubCameraData.nearClipPlane = 0.3f; + CameraSetData(&SubCameraData, NEARCLIPPLANE); + + SubCameraData.farClipPlane = 5.0f; + CameraSetData(&SubCameraData, FARCLIPPLANE); + + CameraTexture.camera = SubCamera; + CameraTextureInit(&CameraTexture); + + SubCameraData.cameraTexture = &CameraTexture; + + + SubCameraMainCameraSubRaster = rw::Raster::create(0, 0, 0, rw::Raster::CAMERA); + SubCameraMainCameraSubZRaster = rw::Raster::create(0, 0, 0, rw::Raster::ZBUFFER); +} + +void +CamerasDestroy(rw::World *world) +{ + SubCameraMiniViewSelect(false); + + if(MainCamera){ + ViewerDestroy(MainCamera, world); + MainCamera = nil; + } + + if(SubCamera){ + ViewerDestroy(SubCamera, world); + SubCamera = nil; + } + + CameraTextureTerm(&CameraTexture); + + if(SubCameraMainCameraSubRaster){ + SubCameraMainCameraSubRaster->destroy(); + SubCameraMainCameraSubRaster = nil; + } + + if(SubCameraMainCameraSubZRaster){ + SubCameraMainCameraSubZRaster->destroy(); + SubCameraMainCameraSubZRaster = nil; + } +} + +void +UpdateSubRaster(rw::Camera *camera, rw::Rect *rect) +{ + rw::Rect subRect; + + subRect.x = rect->w * 0.75f; + subRect.y = 0; + + subRect.w = rect->w * 0.25f; + subRect.h = rect->h * 0.25f; + + SubCameraMainCameraSubRaster->subRaster(camera->frameBuffer, &subRect); + SubCameraMainCameraSubZRaster->subRaster(camera->zBuffer, &subRect); +} + +void +CameraSizeUpdate(rw::Rect *rect, float viewWindow, float aspectRatio) +{ + static bool RasterInit; + + if(MainCamera == nil) + return; + + sk::CameraSize(MainCamera, rect, viewWindow, aspectRatio); + + UpdateSubRaster(MainCamera, rect); + + if(RasterInit) + SubCameraMiniViewSelect(false); + + sk::CameraSize(SubCamera, rect, viewWindow, aspectRatio); + + SubCameraRaster = SubCamera->frameBuffer; + SubCameraZRaster = SubCamera->zBuffer; + + RasterInit = true; + SubCameraMiniViewSelect(CameraSelected == 0); + + CameraQueryData(&SubCameraData, VIEWWINDOW, SubCamera); +} + +void +RenderSubCamera(rw::RGBA *backgroundColor, rw::int32 clearMode, rw::World *world) +{ + SubCamera->clear(backgroundColor, clearMode); + SubCamera->beginUpdate(); + world->render(); + SubCamera->endUpdate(); +} + +void +RenderTextureCamera(rw::RGBA *foregroundColor, rw::int32 clearMode, rw::World *world) +{ + rw::Raster *saveRaster, *saveZRaster; + + saveRaster = CameraTexture.camera->frameBuffer; + saveZRaster = CameraTexture.camera->zBuffer; + CameraTexture.camera->frameBuffer = CameraTexture.raster; + CameraTexture.camera->zBuffer = CameraTexture.zRaster; + + CameraTexture.camera->clear(foregroundColor, clearMode); + CameraTexture.camera->beginUpdate(); + world->render(); + CameraTexture.camera->endUpdate(); + + + CameraTexture.camera->frameBuffer = saveRaster; + CameraTexture.camera->zBuffer = saveZRaster; +} + +void +SubCameraMiniViewSelect(bool select) +{ + if(select){ + SubCamera->frameBuffer = SubCameraMainCameraSubRaster; + SubCamera->zBuffer = SubCameraMainCameraSubZRaster; + }else{ + SubCamera->frameBuffer = SubCameraRaster; + SubCamera->zBuffer = SubCameraZRaster; + } +} + + + +void +CameraTextureInit(TextureCamera *ct) +{ + ct->raster = rw::Raster::create(TEXSIZE, TEXSIZE, 0, rw::Raster::CAMERATEXTURE); + assert(ct->raster); + ct->zRaster = rw::Raster::create(TEXSIZE, TEXSIZE, 0, rw::Raster::ZBUFFER); + assert(ct->zRaster); + + ct->texture = rw::Texture::create(ct->raster); + ct->texture->setFilter(rw::Texture::FilterMode::LINEAR); +} + +void +CameraTextureTerm(TextureCamera *ct) +{ + if(ct->raster){ + ct->raster->destroy(); + ct->raster = nil; + } + + if(ct->zRaster){ + ct->zRaster->destroy(); + ct->zRaster = nil; + } + + if(ct->texture){ + ct->texture->raster = nil; + ct->texture->destroy(); + ct->texture = nil; + } +} + + + +void +DrawCameraFrustum(CameraData *c) +{ + rw::RGBA yellow = { 255, 255, 0, 64 }; + rw::RGBA red = { 255, 0, 0, 255 }; + rw::RWDEVICE::Im3DVertex frustum[13]; + // lines + rw::uint16 indicesL[] = { + 1, 2, 2, 3, 3, 4, 4, 1, + 5, 6, 6, 7, 7, 8, 8, 5, + 9, 10, 10, 11, 11, 12, 12, 9, + 5, 9, 6, 10, 7, 11, 8, 12, + 0, 0 + }; + // triangles + rw::uint16 indicesT[] = { + 5, 6, 10, + 10, 9, 5, + 6, 7, 11, + 11, 10, 6, + 7, 8, 12, + 12, 11, 7, + 8, 5, 9, + 9, 12, 8, + + 7, 6, 5, + 5, 8, 7, + 9, 10, 11, + 11, 12, 9 + }; + float signs[4][2] = { + { 1, 1 }, + { -1, 1 }, + { -1, -1 }, + { 1, -1 } + }; + + float depth[3]; + depth[0] = 1.0f; // view window + depth[1] = c->nearClipPlane; + depth[2] = c->farClipPlane; + + int k = 0; + frustum[k].setX(c->offset.x); + frustum[k].setY(c->offset.y); + frustum[k].setZ(0.0f); + k++; + + for(int i = 0; i < 3; i++) // depths + for(int j = 0; j < 4; j++){ // planes + if(c->projection == rw::Camera::PERSPECTIVE){ + frustum[k].setX(-c->offset.x + depth[i]*(signs[j][0]*c->viewWindow.x + c->offset.x)); + frustum[k].setY(c->offset.y + depth[i]*(signs[j][1]*c->viewWindow.y - c->offset.y)); + frustum[k].setZ(depth[i]); + }else{ + frustum[k].setX(-c->offset.x + signs[j][0]*c->viewWindow.x + depth[i]*c->offset.x); + frustum[k].setY(c->offset.y + signs[j][1]*c->viewWindow.y - depth[i]*c->offset.y); + frustum[k].setZ(depth[i]); + } + k++; + } + + for(int i = 0; i < 5; i++) + frustum[i].setColor(red.red, red.green, red.blue, red.alpha); + for(int i = 5; i < 13; i++) + frustum[i].setColor(yellow.red, yellow.green, yellow.blue, 255); + + rw::SetRenderStatePtr(rw::TEXTURERASTER, nil); + + rw::im3d::Transform(frustum, 13, c->camera->getFrame()->getLTM(), rw::im3d::ALLOPAQUE); + rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPELINELIST, indicesL, 34); + rw::im3d::End(); + + for(int i = 5; i < 13; i++) + frustum[i].setColor(yellow.red, yellow.green, yellow.blue, yellow.alpha); + + rw::SetRenderState(rw::VERTEXALPHA, 1); + + rw::im3d::Transform(frustum, 13, c->camera->getFrame()->getLTM(), rw::im3d::ALLOPAQUE); + rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, indicesT, 36); + rw::im3d::End(); +} + +void +DrawCameraViewplaneTexture(CameraData *c) +{ + rw::RGBA white = { 255, 255, 255, 255 }; + rw::RWDEVICE::Im3DVertex frustum[4]; + rw::uint16 indicesV[] = { + 2, 1, 0, + 0, 3, 2, + 0, 1, 2, + 2, 3, 0 + }; + float uvValues[4][2] = { + { 0.0f, 0.0f }, + { 1.0f, 0.0f }, + { 1.0f, 1.0f }, + { 0.0f, 1.0f } + }; + float signs[4][2] = { + { 1, 1 }, + { -1, 1 }, + { -1, -1 }, + { 1, -1 } + }; + + for(int j = 0; j < 4; j++){ + frustum[j].setX(signs[j][0]*c->viewWindow.x); + frustum[j].setY(signs[j][1]*c->viewWindow.y); + frustum[j].setZ(1.0f); + } + for(int i = 0; i < 4; i++){ + frustum[i].setColor(white.red, white.green, white.blue, white.alpha); + frustum[i].setU(uvValues[i][0]); + frustum[i].setV(uvValues[i][1]); + } + + rw::SetRenderState(rw::VERTEXALPHA, 1); + rw::SetRenderStatePtr(rw::TEXTURERASTER, c->cameraTexture->texture->raster); + + rw::im3d::Transform(frustum, 4, c->camera->getFrame()->getLTM(), rw::im3d::VERTEXUV); + rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, indicesV, 12); + rw::im3d::End(); +} diff --git a/tools/camera/camexamp.h b/tools/camera/camexamp.h new file mode 100644 index 0000000..7df301f --- /dev/null +++ b/tools/camera/camexamp.h @@ -0,0 +1,62 @@ +struct TextureCamera +{ + rw::Raster *raster; + rw::Raster *zRaster; + rw::Camera *camera; + rw::Texture *texture; +}; + +struct CameraData +{ + float farClipPlane; + float nearClipPlane; + rw::uint32 projection; + rw::V2d offset; + rw::V2d viewWindow; + rw::Camera *camera; + TextureCamera *cameraTexture; + rw::Matrix *matrix; +}; + +enum CameraDataType +{ + NONE = 0x00, + FARCLIPPLANE = 0x01, + NEARCLIPPLANE = 0x02, + PROJECTION = 0x04, + OFFSET = 0x08, + VIEWWINDOW = 0x10, + MATRIX = 0x20, + ALL = 0xFF +}; + +extern rw::Camera *MainCamera; +extern rw::Camera *SubCamera; + +extern rw::int32 CameraSelected; +extern rw::int32 ProjectionIndex; + +extern CameraData SubCameraData; + +void CameraQueryData(CameraData *data, CameraDataType type, rw::Camera *camera); +void CameraSetData(CameraData *data, CameraDataType type); + +void ChangeViewOffset(float deltaX, float deltaY); +void ChangeViewWindow(float deltaX, float deltaY); +void ProjectionCallback(void); +void ClipPlaneCallback(void); + +void CamerasCreate(rw::World *world); +void CamerasDestroy(rw::World *world); +void CameraSizeUpdate(rw::Rect *rect, float viewWindow, float aspectRatio); +void RenderSubCamera(rw::RGBA *foregroundColor, rw::int32 clearMode, rw::World *world); +void RenderTextureCamera(rw::RGBA *foregroundColor, rw::int32 clearMode, rw::World *world); +void SubCameraMiniViewSelect(bool select); + +void CameraTextureInit(TextureCamera *ct); +void CameraTextureTerm(TextureCamera *ct); +void DrawCameraFrustum(CameraData *c); +void DrawCameraViewplaneTexture(CameraData *c); + +void ViewerRotate(rw::Camera *camera, float deltaX, float deltaY); +void ViewerTranslate(rw::Camera *camera, float deltaX, float deltaY); diff --git a/tools/camera/files/clump.dff b/tools/camera/files/clump.dff new file mode 100644 index 0000000..960354f Binary files /dev/null and b/tools/camera/files/clump.dff differ diff --git a/tools/camera/files/clump/shinarm.png b/tools/camera/files/clump/shinarm.png new file mode 100644 index 0000000..1dbc402 Binary files /dev/null and b/tools/camera/files/clump/shinarm.png differ diff --git a/tools/camera/files/clump/shinbody.png b/tools/camera/files/clump/shinbody.png new file mode 100644 index 0000000..645b198 Binary files /dev/null and b/tools/camera/files/clump/shinbody.png differ diff --git a/tools/camera/files/clump/shinface.png b/tools/camera/files/clump/shinface.png new file mode 100644 index 0000000..014ca32 Binary files /dev/null and b/tools/camera/files/clump/shinface.png differ diff --git a/tools/camera/files/clump/shinleg.png b/tools/camera/files/clump/shinleg.png new file mode 100644 index 0000000..e56c1c3 Binary files /dev/null and b/tools/camera/files/clump/shinleg.png differ diff --git a/tools/camera/main.cpp b/tools/camera/main.cpp new file mode 100644 index 0000000..5b7a7eb --- /dev/null +++ b/tools/camera/main.cpp @@ -0,0 +1,504 @@ +#include +#include +#include + +#include "viewer.h" +#include "camexamp.h" + +rw::V3d zero = { 0.0f, 0.0f, 0.0f }; +rw::EngineOpenParams engineOpenParams; +float FOV = 70.0f; + +rw::RGBA ForegroundColor = { 200, 200, 200, 255 }; +rw::RGBA BackgroundColor = { 64, 64, 64, 0 }; +rw::RGBA BackgroundColorSub = { 74, 74, 74, 0 }; + +rw::World *World; +rw::Charset *Charset; + +rw::V3d Xaxis = { 1.0f, 0.0, 0.0f }; +rw::V3d Yaxis = { 0.0f, 1.0, 0.0f }; +rw::V3d Zaxis = { 0.0f, 0.0, 1.0f }; + +float TimeDelta; + +rw::Clump *Clump; + +rw::World* +CreateWorld(void) +{ + rw::BBox bb; + + bb.inf.x = bb.inf.y = bb.inf.z = -100.0f; + bb.sup.x = bb.sup.y = bb.sup.z = 100.0f; + + return rw::World::create(&bb); +} + +void +LightsCreate(rw::World *world) +{ + rw::Light *light = rw::Light::create(rw::Light::AMBIENT); + assert(light); + World->addLight(light); + + light = rw::Light::create(rw::Light::DIRECTIONAL); + assert(light); + rw::Frame *frame = rw::Frame::create(); + assert(frame); + frame->rotate(&Xaxis, 30.0f, rw::COMBINEREPLACE); + frame->rotate(&Yaxis, 30.0f, rw::COMBINEPOSTCONCAT); + light->setFrame(frame); + World->addLight(light); +} + +rw::Clump* +ClumpCreate(rw::World *world) +{ + rw::Clump *clump; + rw::StreamFile in; + + rw::Image::setSearchPath("files/clump/"); + const char *filename = "files/clump.dff"; + if(in.open(filename, "rb") == NULL){ + printf("couldn't open file\n"); + return nil; + } + if(!rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL)) + return nil; + clump = rw::Clump::streamRead(&in); + in.close(); + if(clump == nil) + return nil; + + rw::Frame *frame = clump->getFrame(); + rw::V3d pos = { 0.0f, 0.0f, 8.0f }; + frame->translate(&pos, rw::COMBINEREPLACE); + World->addClump(clump); + return clump; +} + +void +ClumpRotate(rw::Clump *clump, rw::Camera *camera, float xAngle, float yAngle) +{ + rw::Matrix *cameraMatrix = &camera->getFrame()->matrix; + rw::Frame *clumpFrame = clump->getFrame(); + rw::V3d pos = clumpFrame->matrix.pos; + + pos = rw::scale(pos, -1.0f); + clumpFrame->translate(&pos, rw::COMBINEPOSTCONCAT); + + clumpFrame->rotate(&cameraMatrix->up, xAngle, rw::COMBINEPOSTCONCAT); + clumpFrame->rotate(&cameraMatrix->right, yAngle, rw::COMBINEPOSTCONCAT); + + pos = rw::scale(pos, -1.0f); + clumpFrame->translate(&pos, rw::COMBINEPOSTCONCAT); +} + +void +ClumpTranslate(rw::Clump *clump, rw::Camera *camera, float xDelta, float yDelta) +{ + rw::Matrix *cameraMatrix = &camera->getFrame()->matrix; + rw::Frame *clumpFrame = clump->getFrame(); + + rw::V3d deltaX = rw::scale(cameraMatrix->right, xDelta); + rw::V3d deltaZ = rw::scale(cameraMatrix->at, yDelta); + rw::V3d delta = rw::add(deltaX, deltaZ); + + clumpFrame->translate(&delta, rw::COMBINEPOSTCONCAT); +} + +void +ClumpSetPosition(rw::Clump *clump, rw::V3d *position) +{ + clump->getFrame()->translate(position, rw::COMBINEREPLACE); +} + +void +Initialize(void) +{ + sk::globals.windowtitle = "Camera example"; + sk::globals.width = 1280; + sk::globals.height = 800; + sk::globals.quit = 0; +} + +bool +Initialize3D(void) +{ + if(!sk::InitRW()) + return false; + + Charset = rw::Charset::create(&ForegroundColor, &BackgroundColor); + + World = CreateWorld(); + + CamerasCreate(World); + LightsCreate(World); + + Clump = ClumpCreate(World); + + rw::SetRenderState(rw::CULLMODE, rw::CULLBACK); + rw::SetRenderState(rw::ZTESTENABLE, 1); + rw::SetRenderState(rw::ZWRITEENABLE, 1); + + ImGui_ImplRW_Init(); + ImGui::StyleColorsClassic(); + + rw::Rect r; + r.x = 0; + r.y = 0; + r.w = sk::globals.width; + r.h = sk::globals.height; + CameraSizeUpdate(&r, 0.5f, 4.0f/3.0f); + + return true; +} + +void +DestroyLight(rw::Light *light, rw::World *world) +{ + world->removeLight(light); + rw::Frame *frame = light->getFrame(); + if(frame){ + light->setFrame(nil); + frame->destroy(); + } + light->destroy(); +} + +void +Terminate3D(void) +{ + if(Clump){ + World->removeClump(Clump); + Clump->destroy(); + Clump = nil; + } + + FORLIST(lnk, World->globalLights){ + rw::Light *light = rw::Light::fromWorld(lnk); + DestroyLight(light, World); + } + FORLIST(lnk, World->localLights){ + rw::Light *light = rw::Light::fromWorld(lnk); + DestroyLight(light, World); + } + + CamerasDestroy(World); + + if(World){ + World->destroy(); + World = nil; + } + + if(Charset){ + Charset->destroy(); + Charset = nil; + } + + sk::TerminateRW(); +} + +bool +attachPlugins(void) +{ + rw::ps2::registerPDSPlugin(40); + rw::ps2::registerPluginPDSPipes(); + + rw::registerMeshPlugin(); + rw::registerNativeDataPlugin(); + rw::registerAtomicRightsPlugin(); + rw::registerMaterialRightsPlugin(); + rw::xbox::registerVertexFormatPlugin(); + rw::registerSkinPlugin(); + rw::registerUserDataPlugin(); + rw::registerHAnimPlugin(); + rw::registerMatFXPlugin(); + rw::registerUVAnimPlugin(); + rw::ps2::registerADCPlugin(); + return true; +} + +void +DisplayOnScreenInfo(void) +{ + char str[256]; + sprintf(str, "View window (%.2f, %.2f)", SubCameraData.viewWindow.x, SubCameraData.viewWindow.y); + Charset->print(str, 100, 100, 0); + sprintf(str, "View offset (%.2f, %.2f)", SubCameraData.offset.x, SubCameraData.offset.y); + Charset->print(str, 100, 120, 0); +} + +void +ResetCameraAndClump(void) +{ + SubCameraData.nearClipPlane = 0.3f; + SubCameraData.farClipPlane = 5.0f; + SubCameraData.projection = rw::Camera::PERSPECTIVE; + SubCameraData.offset.x = 0.0f; + SubCameraData.offset.y = 0.0f; + SubCameraData.viewWindow.x = 0.5f; + SubCameraData.viewWindow.y = 0.38f; + CameraSetData(&SubCameraData, ALL); + ProjectionIndex = 0; + + rw::V3d position = { 3.0f, 0.0f, 8.0f }; + rw::V3d point = { 0.0f, 0.0f, 8.0f }; + ViewerSetPosition(SubCameraData.camera, &position); + ViewerRotate(SubCamera, -90.0f, 0.0f); + + ClumpSetPosition(Clump, &point); +} + +void +Gui(void) +{ + static bool showCameraWindow = true; + ImGui::Begin("Camera", &showCameraWindow); + + ImGui::RadioButton("Main camera", &CameraSelected, 0); + ImGui::RadioButton("Sub camera", &CameraSelected, 1); + + if(ImGui::RadioButton("Perspective", &ProjectionIndex, 0)) + ProjectionCallback(); + if(ImGui::RadioButton("Parallel", &ProjectionIndex, 1)) + ProjectionCallback(); + + if(ImGui::SliderFloat("Near clip-plane", &SubCameraData.nearClipPlane, 0.1f, SubCameraData.farClipPlane-0.1f)) + ClipPlaneCallback(); + if(ImGui::SliderFloat("Far clip-plane", &SubCameraData.farClipPlane, SubCameraData.nearClipPlane+0.1f, 20.0f)) + ClipPlaneCallback(); + + if(ImGui::Button("Reset")) + ResetCameraAndClump(); + + ImGui::End(); +} + +void +MainCameraRender(rw::Camera *camera) +{ + RenderTextureCamera(&BackgroundColorSub, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ, World); + + camera->clear(&BackgroundColor, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ); + + camera->beginUpdate(); + + ImGui_ImplRW_NewFrame(TimeDelta); + + World->render(); + + DrawCameraViewplaneTexture(&SubCameraData); + DrawCameraFrustum(&SubCameraData); + + DisplayOnScreenInfo(); + + Gui(); + ImGui::EndFrame(); + ImGui::Render(); + + camera->endUpdate(); + + + RenderSubCamera(&BackgroundColorSub, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ, World); +} + +void +SubCameraRender(rw::Camera *camera) +{ + camera->clear(&BackgroundColor, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ); + + camera->beginUpdate(); + + ImGui_ImplRW_NewFrame(TimeDelta); + + World->render(); + + DisplayOnScreenInfo(); + + Gui(); + ImGui::EndFrame(); + ImGui::Render(); + + camera->endUpdate(); +} + +void +Render(void) +{ + rw::Camera *camera; + + SubCameraMiniViewSelect(CameraSelected == 0); + + switch(CameraSelected){ + default: + case 0: + camera = MainCamera; + MainCameraRender(camera); + break; + case 1: + camera = SubCamera; + SubCameraRender(camera); + break; + } + camera->showRaster(0); +} + +void +Idle(float timeDelta) +{ + TimeDelta = timeDelta; + Render(); +} + +int MouseX, MouseY; +int MouseDeltaX, MouseDeltaY; +int MouseButtons; + +bool RotateClump; +bool TranslateClump; +bool RotateCamera; +bool TranslateCamera; +bool ViewXWindow; +bool ViewYWindow; +bool ViewXOffset; +bool ViewYOffset; + +bool Ctrl, Alt, Shift; + +void +KeyUp(int key) +{ + switch(key){ + case sk::KEY_LCTRL: + case sk::KEY_RCTRL: + Ctrl = false; + break; + case sk::KEY_LALT: + case sk::KEY_RALT: + Alt = false; + break; + case sk::KEY_LSHIFT: + case sk::KEY_RSHIFT: + Shift = false; + break; + } +} + +void +KeyDown(int key) +{ + switch(key){ + case sk::KEY_LCTRL: + case sk::KEY_RCTRL: + Ctrl = true; + break; + case sk::KEY_LALT: + case sk::KEY_RALT: + Alt = true; + break; + case sk::KEY_LSHIFT: + case sk::KEY_RSHIFT: + Shift = true; + break; + case sk::KEY_ESC: + sk::globals.quit = 1; + break; + } +} + +void +MouseBtn(sk::MouseState *mouse) +{ + MouseButtons = mouse->buttons; + RotateClump = !Ctrl && !Alt && !Shift && !!(MouseButtons&1); + TranslateClump = !Ctrl && !Alt && !Shift && !!(MouseButtons&4); + RotateCamera = Ctrl && !!(MouseButtons&1); + TranslateCamera = Ctrl && !!(MouseButtons&4); + ViewXWindow = Shift && !!(MouseButtons&1); + ViewYWindow = Shift && !!(MouseButtons&4); + ViewXOffset = Alt && !!(MouseButtons&1); + ViewYOffset = Alt && !!(MouseButtons&4); +} + +void +MouseMove(sk::MouseState *mouse) +{ + MouseDeltaX = mouse->posx - MouseX; + MouseDeltaY = mouse->posy - MouseY; + MouseX = mouse->posx; + MouseY = mouse->posy; + + if(RotateClump) + ClumpRotate(Clump, MainCamera, MouseDeltaX, -MouseDeltaY); + if(TranslateClump) + ClumpTranslate(Clump, MainCamera, -MouseDeltaX*0.01f, -MouseDeltaY*0.1f); + if(RotateCamera) + ViewerRotate(SubCamera, -MouseDeltaX*0.1f, MouseDeltaY*0.1f); + if(TranslateCamera) + ViewerTranslate(SubCamera, -MouseDeltaX*0.01f, -MouseDeltaY*0.01f); + if(ViewXWindow) + ChangeViewWindow(-MouseDeltaY*0.01f, 0.0f); + if(ViewYWindow) + ChangeViewWindow(0.0f, -MouseDeltaY*0.01f); + if(ViewXOffset) + ChangeViewOffset(-MouseDeltaY*0.01f, 0.0f); + if(ViewYOffset) + ChangeViewOffset(0.0f, -MouseDeltaY*0.01f); +} + +sk::EventStatus +AppEventHandler(sk::Event e, void *param) +{ + using namespace sk; + Rect *r; + MouseState *ms; + + ImGuiEventHandler(e, param); + ImGuiIO &io = ImGui::GetIO(); + + switch(e){ + case INITIALIZE: + Initialize(); + return EVENTPROCESSED; + case RWINITIALIZE: + return Initialize3D() ? EVENTPROCESSED : EVENTERROR; + case RWTERMINATE: + Terminate3D(); + return EVENTPROCESSED; + case PLUGINATTACH: + return attachPlugins() ? EVENTPROCESSED : EVENTERROR; + case KEYDOWN: + KeyDown(*(int*)param); + return EVENTPROCESSED; + case KEYUP: + KeyUp(*(int*)param); + return EVENTPROCESSED; + case MOUSEBTN: + if(!io.WantCaptureMouse){ + ms = (MouseState*)param; + MouseBtn(ms); + }else + MouseButtons = 0; + return EVENTPROCESSED; + case MOUSEMOVE: + MouseMove((MouseState*)param); + return EVENTPROCESSED; + case RESIZE: + r = (Rect*)param; + // TODO: register when we're minimized + if(r->w == 0) r->w = 1; + if(r->h == 0) r->h = 1; + + sk::globals.width = r->w; + sk::globals.height = r->h; + + CameraSizeUpdate(r, 0.5f, 4.0f/3.0f); + break; + case IDLE: + Idle(*(float*)param); + return EVENTPROCESSED; + } + return sk::EVENTNOTPROCESSED; +} diff --git a/tools/camera/viewer.cpp b/tools/camera/viewer.cpp new file mode 100644 index 0000000..b9732d3 --- /dev/null +++ b/tools/camera/viewer.cpp @@ -0,0 +1,51 @@ +#include +#include + +rw::Camera* +ViewerCreate(rw::World *world) +{ + rw::Camera *camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1); + assert(camera); + camera->setNearPlane(0.1f); + camera->setFarPlane(500.0f); + world->addCamera(camera); + return camera; +} + +void +ViewerDestroy(rw::Camera *camera, rw::World *world) +{ + if(camera && world){ + world->removeCamera(camera); + sk::CameraDestroy(camera); + } +} + +void +ViewerMove(rw::Camera *camera, rw::V3d *offset) +{ + sk::CameraMove(camera, offset); +} + +void +ViewerRotate(rw::Camera *camera, float deltaX, float deltaY) +{ + sk::CameraTilt(camera, nil, deltaY); + sk::CameraPan(camera, nil, deltaX); +} + +void +ViewerTranslate(rw::Camera *camera, float deltaX, float deltaY) +{ + rw::V3d offset; + offset.x = deltaX; + offset.y = deltaY; + offset.z = 0.0f; + sk::CameraMove(camera, &offset); +} + +void +ViewerSetPosition(rw::Camera *camera, rw::V3d *position) +{ + camera->getFrame()->translate(position, rw::COMBINEREPLACE); +} diff --git a/tools/camera/viewer.h b/tools/camera/viewer.h new file mode 100644 index 0000000..acd5d79 --- /dev/null +++ b/tools/camera/viewer.h @@ -0,0 +1,6 @@ +rw::Camera *ViewerCreate(rw::World *world); +void ViewerDestroy(rw::Camera *camera, rw::World *world); +void ViewerMove(rw::Camera *camera, rw::V3d *offset); +void ViewerRotate(rw::Camera *camera, float deltaX, float deltaY); +void ViewerTranslate(rw::Camera *camera, float deltaX, float deltaY); +void ViewerSetPosition(rw::Camera *camera, rw::V3d *position); diff --git a/tools/subrast/main.cpp b/tools/subrast/main.cpp index a86f373..321c650 100644 --- a/tools/subrast/main.cpp +++ b/tools/subrast/main.cpp @@ -74,14 +74,14 @@ CreateClump(rw::World *world) const char *filename = "files/clump.dff"; if(in.open(filename, "rb") == NULL){ printf("couldn't open file\n"); - return false; + return nil; } if(!rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL)) - return false; + return nil; clump = rw::Clump::streamRead(&in); in.close(); if(clump == nil) - return false; + return nil; rw::Frame *frame = clump->getFrame(); frame->rotate(&Xaxis, -120.0f, rw::COMBINEREPLACE); diff --git a/tools/subrast/subrast.cpp b/tools/subrast/subrast.cpp index 0ee4027..73adae3 100644 --- a/tools/subrast/subrast.cpp +++ b/tools/subrast/subrast.cpp @@ -127,466 +127,16 @@ CreateCameras(rw::World *world) void DestroyCameras(rw::World *world) { -} - -/* - -rw::Light *BaseAmbientLight; -bool BaseAmbientLightOn; - -rw::Light *CurrentLight; -rw::Light *AmbientLight; -rw::Light *PointLight; -rw::Light *DirectLight; -rw::Light *SpotLight; -rw::Light *SpotSoftLight; - -float LightRadius = 100.0f; -float LightConeAngle = 45.0f; -rw::RGBAf LightColor = { 1.0f, 1.0f, 1.0f, 1.0f }; - -rw::RGBA LightSolidColor = { 255, 255, 0, 255 }; -bool LightOn = true; -bool LightDrawOn = true; -rw::V3d LightPos = {0.0f, 0.0f, 75.0f}; -rw::int32 LightTypeIndex = 1; - -rw::BBox RoomBBox; - -rw::Light* -CreateBaseAmbientLight(void) -{ - rw::Light *light = rw::Light::create(rw::Light::AMBIENT); - assert(light); - light->setColor(0.5f, 0.5f, 0.5f); - return light; -} - -rw::Light* -CreateAmbientLight(void) -{ - return rw::Light::create(rw::Light::AMBIENT); -} - -rw::Light* -CreateDirectLight(void) -{ - rw::Light *light = rw::Light::create(rw::Light::DIRECTIONAL); - assert(light); - rw::Frame *frame = rw::Frame::create(); - assert(frame); - frame->rotate(&Xaxis, 45.0f, rw::COMBINEREPLACE); - rw::V3d pos = LightPos; - frame->translate(&pos, rw::COMBINEPOSTCONCAT); - light->setFrame(frame); - return light; -} - -rw::Light* -CreatePointLight(void) -{ - rw::Light *light = rw::Light::create(rw::Light::POINT); - assert(light); - light->radius = LightRadius; - rw::Frame *frame = rw::Frame::create(); - assert(frame); - rw::V3d pos = LightPos; - frame->translate(&pos, rw::COMBINEREPLACE); - light->setFrame(frame); - return light; -} - -rw::Light* -CreateSpotLight(void) -{ - rw::Light *light = rw::Light::create(rw::Light::SPOT); - assert(light); - light->radius = LightRadius; - light->setAngle(LightConeAngle/180.0f*M_PI); - rw::Frame *frame = rw::Frame::create(); - assert(frame); - frame->rotate(&Xaxis, 45.0f, rw::COMBINEREPLACE); - rw::V3d pos = LightPos; - frame->translate(&pos, rw::COMBINEPOSTCONCAT); - light->setFrame(frame); - return light; -} - -rw::Light* -CreateSpotSoftLight(void) -{ - rw::Light *light = rw::Light::create(rw::Light::SOFTSPOT); - assert(light); - light->radius = LightRadius; - light->setAngle(LightConeAngle/180.0f*M_PI); - rw::Frame *frame = rw::Frame::create(); - assert(frame); - frame->rotate(&Xaxis, 45.0f, rw::COMBINEREPLACE); - rw::V3d pos = LightPos; - frame->translate(&pos, rw::COMBINEPOSTCONCAT); - light->setFrame(frame); - return light; -} - -void -DestroyLight(rw::Light **light) -{ - if(*light == nil) - return; - rw::World *world = (*light)->world; - if(world) - world->removeLight(*light); - rw::Frame *frame = (*light)->getFrame(); - if(frame){ - (*light)->setFrame(nil); - frame->destroy(); + if(Camera){ + world->removeCamera(Camera); + sk::CameraDestroy(Camera); + Camera = nil; } - (*light)->destroy(); - *light = nil; -} - -void -LightsDestroy(void) -{ - DestroyLight(&SpotSoftLight); - DestroyLight(&SpotLight); - DestroyLight(&PointLight); - DestroyLight(&DirectLight); - DestroyLight(&AmbientLight); - DestroyLight(&BaseAmbientLight); -} - -void -LightsUpdate(void) -{ - static rw::int32 oldLightTypeIndex = -1; - - // Switch to a different light - if((LightOn && oldLightTypeIndex != LightTypeIndex) || CurrentLight == nil){ - oldLightTypeIndex = LightTypeIndex; - - // remove first - if(CurrentLight) - CurrentLight->world->removeLight(CurrentLight); - - switch(LightTypeIndex){ - case 0: CurrentLight = AmbientLight; break; - case 1: CurrentLight = PointLight; break; - case 2: CurrentLight = DirectLight; break; - case 3: CurrentLight = SpotLight; break; - case 4: CurrentLight = SpotSoftLight; break; + for(int i = 0; i < 4; i++) + if(SubCameras[i]){ + world->removeCamera(SubCameras[i]); + sk::CameraDestroy(SubCameras[i]); + SubCameras[i] = nil; } - World->addLight(CurrentLight); - } - - if(CurrentLight){ - CurrentLight->setColor(LightColor.red, LightColor.green, LightColor.blue); - CurrentLight->radius = LightRadius; - CurrentLight->setAngle(LightConeAngle / 180.0f * M_PI); - } - - // Remove light from world if not used - if(!LightOn && CurrentLight){ - CurrentLight->world->removeLight(CurrentLight); - CurrentLight = nil; - } } - -#define POINT_LIGHT_RADIUS_FACTOR 0.05f - -void -DrawPointLight(void) -{ - enum { NUMVERTS = 50 }; - rw::RWDEVICE::Im3DVertex shape[NUMVERTS]; - rw::int32 i; - rw::V3d point; - - rw::V3d *pos = &CurrentLight->getFrame()->getLTM()->pos; - for(i = 0; i < NUMVERTS; i++){ - point.x = pos->x + - cosf(i/(NUMVERTS/2.0f) * M_PI) * LightRadius * POINT_LIGHT_RADIUS_FACTOR; - point.y = pos->y + - sinf(i/(NUMVERTS/2.0f) * M_PI) * LightRadius * POINT_LIGHT_RADIUS_FACTOR; - point.z = pos->z; - - shape[i].setColor(LightSolidColor.red, LightSolidColor.green, - LightSolidColor.blue, LightSolidColor.alpha); - shape[i].setX(point.x); - shape[i].setY(point.y); - shape[i].setZ(point.z); - } - - rw::im3d::Transform(shape, NUMVERTS, nil, rw::im3d::ALLOPAQUE); - rw::im3d::RenderPrimitive(rw::PRIMTYPEPOLYLINE); - rw::im3d::RenderLine(NUMVERTS-1, 0); - rw::im3d::End(); -} - -void -DrawCone(float coneAngle, float coneSize, float coneRatio) -{ - enum { NUMVERTS = 10 }; - rw::RWDEVICE::Im3DVertex shape[NUMVERTS+1]; - rw::int16 indices[NUMVERTS*3]; - rw::int32 i; - - rw::Matrix *matrix = CurrentLight->getFrame()->getLTM(); - rw::V3d *pos = &matrix->pos; - - // cone - for(i = 1; i < NUMVERTS+1; i++){ - float cosValue = cosf(i/(NUMVERTS/2.0f) * M_PI) * - sinf(coneAngle/180.0f*M_PI); - float sinValue = sinf(i/(NUMVERTS/2.0f) * M_PI) * - sinf(coneAngle/180.0f*M_PI); - - float coneAngleD = cosf(coneAngle/180.0f*M_PI); - - rw::V3d up = rw::scale(matrix->up, sinValue*coneSize); - rw::V3d right = rw::scale(matrix->right, cosValue*coneSize); - rw::V3d at = rw::scale(matrix->at, coneAngleD*coneSize*coneRatio); - - shape[i].setX(pos->x + at.x + up.x + right.x); - shape[i].setY(pos->y + at.y + up.y + right.y); - shape[i].setZ(pos->z + at.z + up.z + right.z); - } - - for(i = 0; i < NUMVERTS; i++){ - indices[i*3 + 0] = 0; - indices[i*3 + 1] = i+2; - indices[i*3 + 2] = i+1; - } - indices[NUMVERTS*3-2] = 1; - - for(i = 0; i < NUMVERTS+1; i++) - shape[i].setColor(LightSolidColor.red, LightSolidColor.green, - LightSolidColor.blue, 128); - - shape[0].setX(pos->x); - shape[0].setY(pos->y); - shape[0].setZ(pos->z); - - rw::SetRenderState(rw::VERTEXALPHA, 1); - rw::SetRenderState(rw::SRCBLEND, rw::BLENDSRCALPHA); - rw::SetRenderState(rw::DESTBLEND, rw::BLENDINVSRCALPHA); - - rw::im3d::Transform(shape, NUMVERTS+1, nil, 0); - rw::im3d::RenderPrimitive(rw::PRIMTYPETRIFAN); - rw::im3d::RenderTriangle(0, NUMVERTS, 1); - rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, indices, NUMVERTS*3); - rw::im3d::End(); - - - for(i = 0; i < NUMVERTS+1; i++) - shape[i].setColor(LightSolidColor.red, LightSolidColor.green, - LightSolidColor.blue, 255); - - float coneAngleD = cosf(coneAngle/180.0f*M_PI); - rw::V3d at = rw::scale(matrix->at, coneAngleD*coneSize*coneRatio); - shape[0].setX(pos->x + at.x); - shape[0].setY(pos->y + at.y); - shape[0].setZ(pos->z + at.z); - - rw::im3d::Transform(shape, NUMVERTS+1, nil, rw::im3d::ALLOPAQUE); - if(coneRatio > 0.0f){ - rw::im3d::RenderPrimitive(rw::PRIMTYPETRIFAN); - rw::im3d::RenderTriangle(0, NUMVERTS, 1); - }else - rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRIFAN, indices, NUMVERTS*3); - rw::im3d::End(); - - - // lines - at = rw::scale(matrix->at, -0.05f); - shape[0].setX(pos->x + at.x); - shape[0].setY(pos->y + at.y); - shape[0].setZ(pos->z + at.z); - rw::im3d::Transform(shape, NUMVERTS+1, nil, rw::im3d::ALLOPAQUE); - rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPEPOLYLINE, indices, NUMVERTS*3); - rw::im3d::End(); -} - -void -DrawDirectLight(void) -{ - enum { NUMVERTS = 20 }; - const float DIAMETER = 1.5f; - const float CONE_ANGLE = 45.0f; - const float CONE_SIZE = 3.0f; - const float LENGTH = 5.0f; - rw::RWDEVICE::Im3DVertex shape[NUMVERTS*2+1]; - rw::int16 indices[NUMVERTS*3]; - rw::int32 i; - - rw::Matrix *matrix = CurrentLight->getFrame()->getLTM(); - rw::V3d *pos = &matrix->pos; - - // cylinder - for(i = 0; i < NUMVERTS*2; i += 2){ - float cosValue = cosf(i/(NUMVERTS/2.0f) * M_PI); - float sinValue = sinf(i/(NUMVERTS/2.0f) * M_PI); - - rw::V3d up = rw::scale(matrix->up, sinValue*DIAMETER); - rw::V3d right = rw::scale(matrix->right, cosValue*DIAMETER); - rw::V3d at = rw::scale(matrix->at, -(CONE_SIZE + 1.0f)); - - shape[i].setX(pos->x + at.x + up.x + right.x); - shape[i].setY(pos->y + at.y + up.y + right.y); - shape[i].setZ(pos->z + at.z + up.z + right.z); - - - at = rw::scale(matrix->at, -(LENGTH + CONE_SIZE)); - - shape[i+1].setX(pos->x + at.x + up.x + right.x); - shape[i+1].setY(pos->y + at.y + up.y + right.y); - shape[i+1].setZ(pos->z + at.z + up.z + right.z); - } - - for(i = 0; i < NUMVERTS*2+1; i++) - shape[i].setColor(LightSolidColor.red, LightSolidColor.green, - LightSolidColor.blue, 128); - - rw::SetRenderState(rw::VERTEXALPHA, 1); - rw::SetRenderState(rw::SRCBLEND, rw::BLENDSRCALPHA); - rw::SetRenderState(rw::DESTBLEND, rw::BLENDINVSRCALPHA); - - rw::im3d::Transform(shape, NUMVERTS*2, nil, 0); - rw::im3d::RenderPrimitive(rw::PRIMTYPETRISTRIP); - rw::im3d::RenderTriangle(2*NUMVERTS-2, 2*NUMVERTS-1, 0); - rw::im3d::RenderTriangle(2*NUMVERTS-1, 1, 0); - rw::im3d::End(); - - - // bottom cap - for(i = 0; i < NUMVERTS*2+1; i++) - shape[i].setColor(LightSolidColor.red, LightSolidColor.green, - LightSolidColor.blue, 255); - - rw::V3d at = rw::scale(matrix->at, -(LENGTH + CONE_SIZE)); - shape[NUMVERTS*2].setX(pos->x + at.x); - shape[NUMVERTS*2].setY(pos->y + at.y); - shape[NUMVERTS*2].setZ(pos->z + at.z); - - for(i = 0; i < NUMVERTS; i++){ - indices[i*3+0] = NUMVERTS*2; - indices[i*3+1] = (i+1)*2 + 1; - indices[i*3+2] = i*2 + 1; - } - indices[NUMVERTS*3-2] = 1; - - rw::im3d::Transform(shape, NUMVERTS*2+1, nil, rw::im3d::ALLOPAQUE); - rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, indices, NUMVERTS*3); - rw::im3d::End(); - - - // top cap - at = rw::scale(matrix->at, -(CONE_SIZE + 1.0f)); - shape[NUMVERTS*2].setX(pos->x + at.x); - shape[NUMVERTS*2].setY(pos->y + at.y); - shape[NUMVERTS*2].setZ(pos->z + at.z); - - for(i = 0; i < NUMVERTS; i++){ - indices[i*3+0] = NUMVERTS*2; - indices[i*3+1] = i*2; - indices[i*3+2] = (i+1)*2; - } - - rw::im3d::Transform(shape, NUMVERTS*2+1, nil, rw::im3d::ALLOPAQUE); - rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, indices, NUMVERTS*3); - rw::im3d::End(); - - - // cone - DrawCone(CONE_ANGLE, CONE_SIZE, -2.0f); -} - -void -DrawCurrentLight(void) -{ - rw::SetRenderState(rw::TEXTURERASTER, nil); - rw::SetRenderState(rw::CULLMODE, rw::CULLBACK); - rw::SetRenderState(rw::ZTESTENABLE, 1); - - switch(LightTypeIndex){ - case 1: DrawPointLight(); break; - case 2: DrawDirectLight(); break; - case 3: - case 4: DrawCone(LightConeAngle, LightRadius*POINT_LIGHT_RADIUS_FACTOR, 1.0f); break; - } -} - - - -void -LightRotate(float xAngle, float yAngle) -{ - if(CurrentLight == nil || CurrentLight == AmbientLight || CurrentLight == PointLight) - return; - - rw::Matrix *cameraMatrix = &Camera->getFrame()->matrix; - rw::Frame *lightFrame = CurrentLight->getFrame(); - rw::V3d pos = lightFrame->matrix.pos; - - pos = rw::scale(pos, -1.0f); - lightFrame->translate(&pos, rw::COMBINEPOSTCONCAT); - - lightFrame->rotate(&cameraMatrix->up, xAngle, rw::COMBINEPOSTCONCAT); - lightFrame->rotate(&cameraMatrix->right, yAngle, rw::COMBINEPOSTCONCAT); - - pos = rw::scale(pos, -1.0f); - lightFrame->translate(&pos, rw::COMBINEPOSTCONCAT); -} - -void -ClampPosition(rw::V3d *pos, rw::V3d *delta, rw::BBox *bbox) -{ - if(pos->x + delta->x < bbox->inf.x) - delta->x = bbox->inf.x - pos->x; - else if(pos->x + delta->x > bbox->sup.x) - delta->x = bbox->sup.x - pos->x; - - if(pos->y + delta->y < bbox->inf.y) - delta->y = bbox->inf.y - pos->y; - else if(pos->y + delta->y > bbox->sup.y) - delta->y = bbox->sup.y - pos->y; - - if(pos->z + delta->z < bbox->inf.z) - delta->z = bbox->inf.z - pos->z; - else if(pos->z + delta->z > bbox->sup.z) - delta->z = bbox->sup.z - pos->z; -} - -void -LightTranslateXY(float xDelta, float yDelta) -{ - if(CurrentLight == nil || CurrentLight == AmbientLight || CurrentLight == DirectLight) - return; - - rw::Matrix *cameraMatrix = &Camera->getFrame()->matrix; - rw::Frame *lightFrame = CurrentLight->getFrame(); - rw::V3d right = rw::scale(cameraMatrix->right, xDelta); - rw::V3d up = rw::scale(cameraMatrix->up, yDelta); - rw::V3d delta = rw::add(right, up); - - ClampPosition(&lightFrame->matrix.pos, &delta, &RoomBBox); - - lightFrame->translate(&delta, rw::COMBINEPOSTCONCAT); -} - -void -LightTranslateZ(float zDelta) -{ - if(CurrentLight == nil || CurrentLight == AmbientLight || CurrentLight == DirectLight) - return; - - rw::Matrix *cameraMatrix = &Camera->getFrame()->matrix; - rw::Frame *lightFrame = CurrentLight->getFrame(); - rw::V3d delta = rw::scale(cameraMatrix->at, zDelta); - - ClampPosition(&lightFrame->matrix.pos, &delta, &RoomBBox); - - lightFrame->translate(&delta, rw::COMBINEPOSTCONCAT); -} -*/ \ No newline at end of file