mirror of
https://github.com/aap/librw.git
synced 2024-12-18 06:34:50 +00:00
396 lines
9.4 KiB
C++
396 lines
9.4 KiB
C++
|
#include <rw.h>
|
||
|
#include <skeleton.h>
|
||
|
|
||
|
#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();
|
||
|
}
|