Initial commit

This commit is contained in:
Shinovon 2026-04-22 07:30:27 +05:00
commit 77cdaaf97e
827 changed files with 418745 additions and 0 deletions

20
vendor/librw/tools/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,20 @@
if(LIBRW_TOOLS AND NOT LIBRW_PLATFORM_PS2)
add_subdirectory(dumprwtree)
add_subdirectory(ska2anm)
endif()
if(LIBRW_EXAMPLES)
if(TARGET librw::skeleton)
add_subdirectory(imguitest)
add_subdirectory(playground)
add_subdirectory(lights)
add_subdirectory(subrast)
add_subdirectory(camera)
add_subdirectory(im2d)
add_subdirectory(im3d)
endif()
if(LIBRW_PLATFORM_PS2)
add_subdirectory(ps2test)
endif()
endif()

View file

@ -0,0 +1,19 @@
add_executable(camera WIN32
main.cpp
camexamp.cpp
viewer.cpp
)
target_link_libraries(camera
PRIVATE
librw::skeleton
librw::librw
)
add_custom_command(
TARGET camera POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:camera>/files"
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/files" "$<TARGET_FILE_DIR:camera>/files"
)
librw_platform_target(camera)

395
vendor/librw/tools/camera/camexamp.cpp vendored Normal file
View file

@ -0,0 +1,395 @@
#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();
}

62
vendor/librw/tools/camera/camexamp.h vendored Normal file
View file

@ -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);

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

508
vendor/librw/tools/camera/main.cpp vendored Normal file
View file

@ -0,0 +1,508 @@
#include <rw.h>
#include <skeleton.h>
#include <assert.h>
#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();
ImGui_ImplRW_RenderDrawLists(ImGui::GetDrawData());
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();
ImGui_ImplRW_RenderDrawLists(ImGui::GetDrawData());
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;
}

51
vendor/librw/tools/camera/viewer.cpp vendored Normal file
View file

@ -0,0 +1,51 @@
#include <rw.h>
#include <skeleton.h>
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);
}

6
vendor/librw/tools/camera/viewer.h vendored Normal file
View file

@ -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);

View file

@ -0,0 +1,16 @@
add_executable(dumprwtree
dumprwtree.cpp
)
target_link_libraries(dumprwtree
PRIVATE
librw::librw
)
if(LIBRW_INSTALL)
install(TARGETS dumprwtree
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
endif()
librw_platform_target(dumprwtree INSTALL)

View file

@ -0,0 +1,145 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <rw.h>
using namespace std;
using namespace rw;
const char *chunks[] = { "None", "Struct", "String", "Extension", "Unknown",
"Camera", "Texture", "Material", "Material List", "Atomic Section",
"Plane Section", "World", "Spline", "Matrix", "Frame List",
"Geometry", "Clump", "Unknown", "Light", "Unicode String", "Atomic",
"Texture Native", "Texture Dictionary", "Animation Database",
"Image", "Skin Animation", "Geometry List", "Anim Animation",
"Team", "Crowd", "Delta Morph Animation", "Right To Render",
"MultiTexture Effect Native", "MultiTexture Effect Dictionary",
"Team Dictionary", "Platform Independet Texture Dictionary",
"Table of Contents", "Particle Standard Global Data", "AltPipe",
"Platform Independet Peds", "Patch Mesh", "Chunk Group Start",
"Chunk Group End", "UV Animation Dictionary", "Coll Tree"
};
/* From 0x0101 through 0x0135 */
const char *toolkitchunks0[] = { "Metrics PLG", "Spline PLG", "Stereo PLG",
"VRML PLG", "Morph PLG", "PVS PLG", "Memory Leak PLG", "Animation PLG",
"Gloss PLG", "Logo PLG", "Memory Info PLG", "Random PLG",
"PNG Image PLG", "Bone PLG", "VRML Anim PLG", "Sky Mipmap Val",
"MRM PLG", "LOD Atomic PLG", "ME PLG", "Lightmap PLG",
"Refine PLG", "Skin PLG", "Label PLG", "Particles PLG", "GeomTX PLG",
"Synth Core PLG", "STQPP PLG",
"Part PP PLG", "Collision PLG", "HAnim PLG", "User Data PLG",
"Material Effects PLG", "Particle System PLG", "Delta Morph PLG",
"Patch PLG", "Team PLG", "Crowd PP PLG", "Mip Split PLG",
"Anisotrophy PLG", "Not used", "GCN Material PLG", "Geometric PVS PLG",
"XBOX Material PLG", "Multi Texture PLG", "Chain PLG", "Toon PLG",
"PTank PLG", "Particle Standard PLG", "PDS PLG", "PrtAdv PLG",
"Normal Map PLG", "ADC PLG", "UV Animation PLG"
};
/* From 0x0180 through 0x01c1 */
const char *toolkitchunks1[] = {
"Character Set PLG", "NOHS World PLG", "Import Util PLG",
"Slerp PLG", "Optim PLG", "TL World PLG", "Database PLG",
"Raytrace PLG", "Ray PLG", "Library PLG",
"Not used", "Not used", "Not used", "Not used", "Not used", "Not used",
"2D PLG", "Tile Render PLG", "JPEG Image PLG", "TGA Image PLG",
"GIF Image PLG", "Quat PLG", "Spline PVS PLG", "Mipmap PLG",
"MipmapK PLG", "2D Font", "Intersection PLG", "TIFF Image PLG",
"Pick PLG", "BMP Image PLG", "RAS Image PLG", "Skin FX PLG",
"VCAT PLG", "2D Path", "2D Brush", "2D Object", "2D Shape", "2D Scene",
"2D Pick Region", "2D Object String", "2D Animation PLG",
"2D Animation",
"Not used", "Not used", "Not used", "Not used", "Not used", "Not used",
"2D Keyframe", "2D Maestro", "Barycentric",
"Platform Independent Texture Dictionary TK", "TOC TK", "TPL TK",
"AltPipe TK", "Animation TK", "Skin Split Tookit", "Compressed Key TK",
"Geometry Conditioning PLG", "Wing PLG", "Generic Pipeline TK",
"Lightmap Conversion TK", "Filesystem PLG", "Dictionary TK",
"UV Animation Linear", "UV Animation Parameter"
};
const char *RSchunks[] = { "Unused 1", "Unused 2", "Extra Normals",
"Pipeline Set", "Unused 5", "Unused 6", "Specular Material",
"Unused 8", "2dfx", "Extra Colors", "Collision Model",
"Unused 12", "Environment Material", "Breakable", "Node Name",
"Unused 16"
};
const char*
getChunkName(uint32 id)
{
switch(id){
case 0x50E:
return "Bin Mesh PLG";
case 0x510:
return "Native Data PLG";
case 0x511:
return "Vertex Format PLG";
case 0xF21E:
return "ZModeler Lock";
}
if(id <= 45)
return chunks[id];
else if(id <= 0x0253F2FF && id >= 0x0253F2F0)
return RSchunks[id-0x0253F2F0];
else if(id <= 0x0135 && id >= 0x0101)
return toolkitchunks0[id-0x0101];
else if(id <= 0x01C0 && id >= 0x0181)
return toolkitchunks1[id-0x0181];
else
return "Unknown";
}
void
readchunk(StreamFile *s, ChunkHeaderInfo *h, int level)
{
for(int i = 0; i < level; i++)
printf(" ");
const char *name = getChunkName(h->type);
printf("%s (%x bytes @ 0x%x/0x%x) - [0x%x]\n",
name, h->length, s->tell()-12, s->tell(), h->type);
uint32 end = s->tell() + h->length;
while(s->tell() < end){
ChunkHeaderInfo nh;
readChunkHeaderInfo(s, &nh);
if(nh.version == h->version && nh.build == h->build){
readchunk(s, &nh, level+1);
if(h->type == 0x510)
s->seek(end, 0);
}else{
s->seek(h->length-12);
break;
}
}
}
int
main(int argc, char *argv[])
{
if(argc < 2){
fprintf(stderr, "usage: %s rwStreamFile\n", argv[0]);
return 0;
}
StreamFile s;
s.open(argv[1], "rb");
ChunkHeaderInfo header, last;
while(readChunkHeaderInfo(&s, &header)){
if(header.type == 0)
break;
last = header;
if(argc == 2)
readchunk(&s, &header, 0);
}
printf("%x %x %x\n", last.version, last.build,
libraryIDPack(last.version, last.build));
s.close();
return 0;
}

23
vendor/librw/tools/im2d/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,23 @@
add_executable(im2d WIN32
im2d.cpp
linelist.cpp
main.cpp
polyline.cpp
trifan.cpp
trilist.cpp
tristrip.cpp
)
target_link_libraries(im2d
PRIVATE
librw::skeleton
librw::librw
)
add_custom_command(
TARGET im2d POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:im2d>/files"
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/files" "$<TARGET_FILE_DIR:im2d>/files"
)
librw_platform_target(im2d)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

134
vendor/librw/tools/im2d/im2d.cpp vendored Normal file
View file

@ -0,0 +1,134 @@
#include <rw.h>
#include <skeleton.h>
#include "im2d.h"
bool Im2DColored = true;
bool Im2DTextured;
rw::int32 Im2DPrimType;
rw::V2d ScreenSize;
float Scale;
rw::RGBA SolidWhite = {255, 255, 255, 255};
rw::RGBA SolidBlack = {0, 0, 0, 255};
rw::RGBA SolidRed = {200, 64, 64, 255};
rw::RGBA SolidGreen = {64, 200, 64, 255};
rw::RGBA SolidBlue = {64, 64, 200, 255};
rw::RGBA SolidYellow = {200, 200, 64, 255};
rw::RGBA SolidPurple = {200, 64, 200, 255};
rw::RGBA SolidCyan = {64, 200, 200, 255};
rw::Texture *Im2DTexture;
void
Im2DInitialize(rw::Camera *camera)
{
ScreenSize.x = camera->frameBuffer->width;
ScreenSize.y = camera->frameBuffer->height;
Scale = ScreenSize.y / 3.0f;
rw::Image::setSearchPath("files/");
Im2DTexture = rw::Texture::read("whiteash", nil);
LineListCreate(camera);
LineListSetColor(!Im2DColored);
IndexedLineListCreate(camera);
IndexedLineListSetColor(!Im2DColored);
PolyLineCreate(camera);
PolyLineSetColor(!Im2DColored);
IndexedPolyLineCreate(camera);
IndexedPolyLineSetColor(!Im2DColored);
TriListCreate(camera);
TriListSetColor(!Im2DColored);
IndexedTriListCreate(camera);
IndexedTriListSetColor(!Im2DColored);
TriStripCreate(camera);
TriStripSetColor(!Im2DColored);
IndexedTriStripCreate(camera);
IndexedTriStripSetColor(!Im2DColored);
TriFanCreate(camera);
TriFanSetColor(!Im2DColored);
IndexedTriFanCreate(camera);
IndexedTriFanSetColor(!Im2DColored);
}
void
Im2DTerminate(void)
{
if(Im2DTexture){
Im2DTexture->destroy();
Im2DTexture = nil;
}
}
void
Im2DRender(void)
{
rw::SetRenderState(rw::ZTESTENABLE, 0);
rw::SetRenderState(rw::ZWRITEENABLE, 0);
rw::SetRenderState(rw::SRCBLEND, rw::BLENDSRCALPHA);
rw::SetRenderState(rw::DESTBLEND, rw::BLENDINVSRCALPHA);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::FilterMode::LINEAR);
if(Im2DTextured)
rw::SetRenderStatePtr(rw::TEXTURERASTER, Im2DTexture->raster);
else
rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
switch(Im2DPrimType){
case 0: LineListRender(); break;
case 1: IndexedLineListRender(); break;
case 2: PolyLineRender(); break;
case 3: IndexedPolyLineRender(); break;
case 4: TriListRender(); break;
case 5: IndexedTriListRender(); break;
case 6: TriStripRender(); break;
case 7: IndexedTriStripRender(); break;
case 8: TriFanRender(); break;
case 9: IndexedTriFanRender(); break;
}
}
void
Im2DSize(rw::Camera *camera, rw::int32 w, rw::int32 h)
{
ScreenSize.x = w;
ScreenSize.y = h;
if(ScreenSize.x > ScreenSize.y)
Scale = ScreenSize.y / 3.0f;
else
Scale = ScreenSize.x / 3.0f;
LineListCreate(camera);
IndexedLineListCreate(camera);
PolyLineCreate(camera);
IndexedPolyLineCreate(camera);
TriListCreate(camera);
IndexedTriListCreate(camera);
TriStripCreate(camera);
IndexedTriStripCreate(camera);
TriFanCreate(camera);
IndexedTriFanCreate(camera);
}

62
vendor/librw/tools/im2d/im2d.h vendored Normal file
View file

@ -0,0 +1,62 @@
extern bool Im2DColored;
extern bool Im2DTextured;
extern rw::int32 Im2DPrimType;
extern rw::V2d ScreenSize;
extern float Scale;
extern rw::RGBA SolidWhite;
extern rw::RGBA SolidBlack;
extern rw::RGBA SolidRed;
extern rw::RGBA SolidGreen;
extern rw::RGBA SolidBlue;
extern rw::RGBA SolidYellow;
extern rw::RGBA SolidPurple;
extern rw::RGBA SolidCyan;
void Im2DInitialize(rw::Camera *camera);
void Im2DTerminate(void);
void Im2DRender(void);
void Im2DSize(rw::Camera *camera, rw::int32 w, rw::int32 h);
void LineListCreate(rw::Camera *camera);
void LineListSetColor(bool white);
void LineListRender(void);
void IndexedLineListCreate(rw::Camera *camera);
void IndexedLineListSetColor(bool white);
void IndexedLineListRender(void);
void PolyLineCreate(rw::Camera *camera);
void PolyLineSetColor(bool white);
void PolyLineRender(void);
void IndexedPolyLineCreate(rw::Camera *camera);
void IndexedPolyLineSetColor(bool white);
void IndexedPolyLineRender(void);
void TriListCreate(rw::Camera *camera);
void TriListSetColor(bool white);
void TriListRender(void);
void IndexedTriListCreate(rw::Camera *camera);
void IndexedTriListSetColor(bool white);
void IndexedTriListRender(void);
void TriStripCreate(rw::Camera *camera);
void TriStripSetColor(bool white);
void TriStripRender(void);
void IndexedTriStripCreate(rw::Camera *camera);
void IndexedTriStripSetColor(bool white);
void IndexedTriStripRender(void);
void TriFanCreate(rw::Camera *camera);
void TriFanSetColor(bool white);
void TriFanRender(void);
void IndexedTriFanCreate(rw::Camera *camera);
void IndexedTriFanSetColor(bool white);
void IndexedTriFanRender(void);

159
vendor/librw/tools/im2d/linelist.cpp vendored Normal file
View file

@ -0,0 +1,159 @@
#include <rw.h>
#include <skeleton.h>
#include "im2d.h"
float LineListData[32][4] = {
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.000f, 1.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.383f, 0.924f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.707f, 0.707f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.924f, 0.383f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 1.000f, 0.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.924f, -0.383f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.707f, -0.707f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.383f, -0.924f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.000f, -1.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{-0.383f, -0.924f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{-0.707f, -0.707f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{-0.924f, -0.383f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{-1.000f, 0.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{-0.924f, 0.383f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{-0.707f, 0.707f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f},
{-0.383f, 0.924f, 1.000f, 1.000f}
};
float IndexedLineListData[16][4] = {
{-1.000f, 1.000f, 0.000f, 1.000f},
{-0.500f, 1.000f, 0.250f, 1.000f},
{ 0.000f, 1.000f, 0.500f, 1.000f},
{ 0.500f, 1.000f, 0.750f, 1.000f},
{ 1.000f, 1.000f, 1.000f, 1.000f},
{-1.000f, 0.500f, 0.000f, 0.750f},
{-1.000f, 0.000f, 0.000f, 0.500f},
{-1.000f, -0.500f, 0.000f, 0.250f},
{ 1.000f, 0.500f, 1.000f, 0.750f},
{ 1.000f, 0.000f, 1.000f, 0.500f},
{ 1.000f, -0.500f, 1.000f, 0.250f},
{-1.000f, -1.000f, 0.000f, 0.000f},
{-0.500f, -1.000f, 0.250f, 0.000f},
{ 0.000f, -1.000f, 0.500f, 0.000f},
{ 0.500f, -1.000f, 0.750f, 0.000f},
{ 1.000f, -1.000f, 1.000f, 0.000f}
};
rw::uint16 IndexedLineListIndices[20] = {
0, 11, 1, 12, 2, 13, 3, 14, 4, 15,
0, 4, 5, 8, 6, 9, 7, 10, 11, 15
};
rw::RWDEVICE::Im2DVertex LineList[32];
rw::RWDEVICE::Im2DVertex IndexedLineList[16];
void
LineListCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 32; i++){
LineList[i].setScreenX(ScreenSize.x/2.0f + LineListData[i][0]*Scale);
LineList[i].setScreenY(ScreenSize.y/2.0f - LineListData[i][1]*Scale);
LineList[i].setScreenZ(rw::im2d::GetNearZ());
LineList[i].setRecipCameraZ(recipZ);
LineList[i].setU(LineListData[i][2], recipZ);
LineList[i].setV(LineListData[i][3], recipZ);
}
}
void
LineListSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidRed;
rw::RGBA SolidColor2 = SolidWhite;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
}
for(int i = 0; i < 32; i += 2){
LineList[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
LineList[i+1].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
}
}
void
LineListRender(void)
{
rw::im2d::RenderPrimitive(rw::PRIMTYPELINELIST, LineList, 32);
}
void
IndexedLineListCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 16; i++){
IndexedLineList[i].setScreenX(ScreenSize.x/2.0f + IndexedLineListData[i][0]*Scale);
IndexedLineList[i].setScreenY(ScreenSize.y/2.0f - IndexedLineListData[i][1]*Scale);
IndexedLineList[i].setScreenZ(rw::im2d::GetNearZ());
IndexedLineList[i].setRecipCameraZ(recipZ);
IndexedLineList[i].setU(IndexedLineListData[i][2], recipZ);
IndexedLineList[i].setV(IndexedLineListData[i][3], recipZ);
}
}
void
IndexedLineListSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidRed;
if(white)
SolidColor1 = SolidWhite;
for(int i = 0; i < 16; i++)
IndexedLineList[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
IndexedLineListRender(void)
{
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPELINELIST,
IndexedLineList, 16, IndexedLineListIndices, 20);
}

254
vendor/librw/tools/im2d/main.cpp vendored Normal file
View file

@ -0,0 +1,254 @@
#include <rw.h>
#include <skeleton.h>
#include <assert.h>
#include "im2d.h"
rw::EngineOpenParams engineOpenParams;
rw::RGBA ForegroundColor = { 200, 200, 200, 255 };
rw::RGBA BackgroundColor = { 64, 64, 64, 0 };
rw::Camera *Camera;
rw::Charset *Charset;
float TimeDelta;
rw::Camera*
CreateCamera(void)
{
Camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
assert(Camera);
Camera->setNearPlane(0.1f);
Camera->setFarPlane(10.0f);
return Camera;
}
void
Initialize(void)
{
sk::globals.windowtitle = "Im2D 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);
Camera = CreateCamera();
Im2DInitialize(Camera);
ImGui_ImplRW_Init();
ImGui::StyleColorsClassic();
return true;
}
void
Terminate3D(void)
{
Im2DTerminate();
if(Camera){
Camera->destroy();
Camera = 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)
{
}
void
Gui(void)
{
static bool showWindow = true;
ImGui::Begin("Im2D", &showWindow);
ImGui::RadioButton("Line-list", &Im2DPrimType, 0);
ImGui::RadioButton("Line-list indexed", &Im2DPrimType, 1);
ImGui::RadioButton("Poly-line", &Im2DPrimType, 2);
ImGui::RadioButton("Poly-line indexed", &Im2DPrimType, 3);
ImGui::RadioButton("Tri-list", &Im2DPrimType, 4);
ImGui::RadioButton("Tri-list indexed", &Im2DPrimType, 5);
ImGui::RadioButton("Tri-strip", &Im2DPrimType, 6);
ImGui::RadioButton("Tri-strip indexed", &Im2DPrimType, 7);
ImGui::RadioButton("Tri-fan", &Im2DPrimType, 8);
ImGui::RadioButton("Tri-fan indexed", &Im2DPrimType, 9);
ImGui::NewLine();
ImGui::Checkbox("Textured", &Im2DTextured);
if(ImGui::Checkbox("Colored", &Im2DColored)){
LineListSetColor(!Im2DColored);
IndexedLineListSetColor(!Im2DColored);
PolyLineSetColor(!Im2DColored);
IndexedPolyLineSetColor(!Im2DColored);
TriListSetColor(!Im2DColored);
IndexedTriListSetColor(!Im2DColored);
TriStripSetColor(!Im2DColored);
IndexedTriStripSetColor(!Im2DColored);
TriFanSetColor(!Im2DColored);
IndexedTriFanSetColor(!Im2DColored);
}
ImGui::End();
}
void
Render(void)
{
Camera->clear(&BackgroundColor, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
Camera->beginUpdate();
ImGui_ImplRW_NewFrame(TimeDelta);
Im2DRender();
DisplayOnScreenInfo();
Gui();
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplRW_RenderDrawLists(ImGui::GetDrawData());
Camera->endUpdate();
Camera->showRaster(0);
}
void
Idle(float timeDelta)
{
TimeDelta = timeDelta;
Render();
}
int MouseX, MouseY;
int MouseDeltaX, MouseDeltaY;
int MouseButtons;
void
KeyUp(int key)
{
}
void
KeyDown(int key)
{
switch(key){
case sk::KEY_ESC:
sk::globals.quit = 1;
break;
}
}
void
MouseBtn(sk::MouseState *mouse)
{
MouseButtons = mouse->buttons;
}
void
MouseMove(sk::MouseState *mouse)
{
MouseDeltaX = mouse->posx - MouseX;
MouseDeltaY = mouse->posy - MouseY;
MouseX = mouse->posx;
MouseY = mouse->posy;
}
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;
if(::Camera){
sk::CameraSize(::Camera, r, 0.5f, 4.0f/3.0f);
Im2DSize(::Camera, r->w, r->h);
}
break;
case IDLE:
Idle(*(float*)param);
return EVENTPROCESSED;
}
return sk::EVENTNOTPROCESSED;
}

132
vendor/librw/tools/im2d/polyline.cpp vendored Normal file
View file

@ -0,0 +1,132 @@
#include <rw.h>
#include <skeleton.h>
#include "im2d.h"
float PolyLineData[16][4] = {
{ 0.000f, 1.000f, 0.500f, 1.000f},
{ 0.672f, 0.672f, 0.836f, 0.836f},
{ 0.900f, 0.000f, 0.950f, 0.500f},
{ 0.601f, -0.601f, 0.800f, 0.200f},
{ 0.000f, -0.800f, 0.500f, 0.100f},
{-0.530f, -0.530f, 0.245f, 0.245f},
{-0.700f, 0.000f, 0.150f, 0.500f},
{-0.460f, 0.460f, 0.270f, 0.770f},
{ 0.000f, 0.600f, 0.500f, 0.800f},
{ 0.389f, 0.389f, 0.695f, 0.695f},
{ 0.500f, 0.000f, 0.750f, 0.500f},
{ 0.318f, -0.318f, 0.659f, 0.341f},
{ 0.000f, -0.400f, 0.500f, 0.300f},
{-0.247f, -0.247f, 0.376f, 0.376f},
{-0.300f, 0.000f, 0.350f, 0.500f},
{-0.177f, 0.177f, 0.411f, 0.589f}
};
float IndexedPolyLineData[21][4] = {
{ 0.000f, 1.000f, 0.500f, 1.000f},
{-0.200f, 0.600f, 0.400f, 0.800f},
{ 0.200f, 0.600f, 0.600f, 0.800f},
{-0.400f, 0.200f, 0.300f, 0.600f},
{ 0.000f, 0.200f, 0.500f, 0.600f},
{ 0.400f, 0.200f, 0.700f, 0.600f},
{-0.600f, -0.200f, 0.200f, 0.400f},
{-0.200f, -0.200f, 0.400f, 0.400f},
{ 0.200f, -0.200f, 0.600f, 0.400f},
{ 0.600f, -0.200f, 0.800f, 0.400f},
{-0.800f, -0.600f, 0.100f, 0.200f},
{-0.400f, -0.600f, 0.300f, 0.200f},
{ 0.000f, -0.600f, 0.500f, 0.200f},
{ 0.400f, -0.600f, 0.700f, 0.200f},
{ 0.800f, -0.600f, 0.900f, 0.200f},
{-1.000f, -1.000f, 0.000f, 0.000f},
{-0.600f, -1.000f, 0.200f, 0.000f},
{-0.200f, -1.000f, 0.400f, 0.000f},
{ 0.200f, -1.000f, 0.600f, 0.000f},
{ 0.600f, -1.000f, 0.800f, 0.000f},
{ 1.000f, -1.000f, 1.000f, 0.000f}
};
rw::uint16 IndexedPolyLineIndices[46] = {
0, 2, 5, 4, 8, 5, 9, 8, 13, 9,
14, 13, 19, 14, 20, 19, 18, 13, 12, 8,
7, 12, 18, 17, 12, 11, 17, 16, 15, 10,
16, 11, 10, 6, 11, 7, 6, 3, 7, 4,
3, 1, 4, 2, 1, 0
};
rw::RWDEVICE::Im2DVertex PolyLine[16];
rw::RWDEVICE::Im2DVertex IndexedPolyLine[21];
void
PolyLineCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 16; i++){
PolyLine[i].setScreenX(ScreenSize.x/2.0f + PolyLineData[i][0]*Scale);
PolyLine[i].setScreenY(ScreenSize.y/2.0f - PolyLineData[i][1]*Scale);
PolyLine[i].setScreenZ(rw::im2d::GetNearZ());
PolyLine[i].setRecipCameraZ(recipZ);
PolyLine[i].setU(PolyLineData[i][2], recipZ);
PolyLine[i].setV(PolyLineData[i][3], recipZ);
}
}
void
PolyLineSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidBlue;
if(white)
SolidColor1 = SolidWhite;
for(int i = 0; i < 16; i++)
PolyLine[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
PolyLineRender(void)
{
rw::im2d::RenderPrimitive(rw::PRIMTYPEPOLYLINE, PolyLine, 16);
}
void
IndexedPolyLineCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 21; i++){
IndexedPolyLine[i].setScreenX(ScreenSize.x/2.0f + IndexedPolyLineData[i][0]*Scale);
IndexedPolyLine[i].setScreenY(ScreenSize.y/2.0f - IndexedPolyLineData[i][1]*Scale);
IndexedPolyLine[i].setScreenZ(rw::im2d::GetNearZ());
IndexedPolyLine[i].setRecipCameraZ(recipZ);
IndexedPolyLine[i].setU(IndexedPolyLineData[i][2], recipZ);
IndexedPolyLine[i].setV(IndexedPolyLineData[i][3], recipZ);
}
}
void
IndexedPolyLineSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidBlue;
if(white)
SolidColor1 = SolidWhite;
for(int i = 0; i < 21; i++)
IndexedPolyLine[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
IndexedPolyLineRender(void)
{
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPEPOLYLINE,
IndexedPolyLine, 21, IndexedPolyLineIndices, 46);
}

119
vendor/librw/tools/im2d/trifan.cpp vendored Normal file
View file

@ -0,0 +1,119 @@
#include <rw.h>
#include <skeleton.h>
#include "im2d.h"
float TriFanData[17][4] = {
{ 0.000f, 1.000f, 0.500f, 1.000f},
{-0.383f, 0.924f, 0.308f, 0.962f},
{-0.707f, 0.707f, 0.146f, 0.854f},
{-0.924f, 0.383f, 0.038f, 0.692f},
{-1.000f, 0.000f, 0.000f, 0.500f},
{-0.924f, -0.383f, 0.038f, 0.308f},
{-0.707f, -0.707f, 0.146f, 0.146f},
{-0.383f, -0.924f, 0.308f, 0.038f},
{ 0.000f, -1.000f, 0.500f, 0.000f},
{ 0.383f, -0.924f, 0.692f, 0.038f},
{ 0.707f, -0.707f, 0.854f, 0.146f},
{ 0.924f, -0.383f, 0.962f, 0.308f},
{ 1.000f, 0.000f, 1.000f, 0.500f},
{ 0.924f, 0.383f, 0.962f, 0.692f},
{ 0.707f, 0.707f, 0.854f, 0.854f},
{ 0.383f, 0.924f, 0.692f, 0.962f},
{ 0.000f, 1.000f, 0.500f, 1.000f}
};
float IndexedTriFanData[16][4] = {
{ 0.000f, 1.000f, 0.500f, 1.000f},
{-0.383f, 0.924f, 0.308f, 0.962f},
{-0.707f, 0.707f, 0.146f, 0.854f},
{-0.924f, 0.383f, 0.038f, 0.692f},
{-1.000f, 0.000f, 0.000f, 0.500f},
{-0.924f, -0.383f, 0.038f, 0.308f},
{-0.707f, -0.707f, 0.146f, 0.146f},
{-0.383f, -0.924f, 0.308f, 0.038f},
{ 0.000f, -1.000f, 0.500f, 0.000f},
{ 0.383f, -0.924f, 0.692f, 0.038f},
{ 0.707f, -0.707f, 0.854f, 0.146f},
{ 0.924f, -0.383f, 0.962f, 0.308f},
{ 1.000f, 0.000f, 1.000f, 0.500f},
{ 0.924f, 0.383f, 0.962f, 0.692f},
{ 0.707f, 0.707f, 0.854f, 0.854f},
{ 0.383f, 0.924f, 0.692f, 0.962f}
};
rw::uint16 IndexedTriFanIndices[17] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0
};
rw::RWDEVICE::Im2DVertex TriFan[17];
rw::RWDEVICE::Im2DVertex IndexedTriFan[16];
void
TriFanCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 17; i++){
TriFan[i].setScreenX(ScreenSize.x/2.0f + TriFanData[i][0]*Scale);
TriFan[i].setScreenY(ScreenSize.y/2.0f - TriFanData[i][1]*Scale);
TriFan[i].setScreenZ(rw::im2d::GetNearZ());
TriFan[i].setRecipCameraZ(recipZ);
TriFan[i].setU(TriFanData[i][2], recipZ);
TriFan[i].setV(TriFanData[i][3], recipZ);
}
}
void
TriFanSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidYellow;
if(white)
SolidColor1 = SolidWhite;
for(int i = 0; i < 17; i++)
TriFan[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
TriFanRender(void)
{
rw::im2d::RenderPrimitive(rw::PRIMTYPETRIFAN, TriFan, 17);
}
void
IndexedTriFanCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 16; i++){
IndexedTriFan[i].setScreenX(ScreenSize.x/2.0f + IndexedTriFanData[i][0]*Scale);
IndexedTriFan[i].setScreenY(ScreenSize.y/2.0f - IndexedTriFanData[i][1]*Scale);
IndexedTriFan[i].setScreenZ(rw::im2d::GetNearZ());
IndexedTriFan[i].setRecipCameraZ(recipZ);
IndexedTriFan[i].setU(IndexedTriFanData[i][2], recipZ);
IndexedTriFan[i].setV(IndexedTriFanData[i][3], recipZ);
}
}
void
IndexedTriFanSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidGreen;
if(white)
SolidColor1 = SolidWhite;
for(int i = 0; i < 16; i++)
IndexedTriFan[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
IndexedTriFanRender(void)
{
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRIFAN,
IndexedTriFan, 16, IndexedTriFanIndices, 17);
}

166
vendor/librw/tools/im2d/trilist.cpp vendored Normal file
View file

@ -0,0 +1,166 @@
#include <rw.h>
#include <skeleton.h>
#include "im2d.h"
float TriListData[18][4] = {
{ 0.000f, 1.000f, 0.500f, 1.000f},
{-0.500f, 0.500f, 0.250f, 0.750f},
{ 0.500f, 0.500f, 0.750f, 0.750f},
{-0.500f, 0.500f, 0.250f, 0.750f},
{ 0.500f, -0.500f, 0.750f, 0.250f},
{ 0.500f, 0.500f, 0.750f, 0.750f},
{ 0.500f, 0.500f, 0.750f, 0.750f},
{ 0.500f, -0.500f, 0.750f, 0.250f},
{ 1.000f, 0.000f, 1.000f, 0.500f},
{ 0.500f, -0.500f, 0.750f, 0.250f},
{-0.500f, -0.500f, 0.250f, 0.250f},
{ 0.000f, -1.000f, 0.500f, 0.000f},
{ 0.500f, -0.500f, 0.750f, 1.250f},
{-0.500f, 0.500f, 0.250f, 1.750f},
{-0.500f, -0.500f, 0.250f, 1.250f},
{-0.500f, -0.500f, 0.250f, 0.250f},
{-0.500f, 0.500f, 0.250f, 0.750f},
{-1.000f, 0.000f, 0.000f, 0.500f}
};
float IndexedTriListData[21][4] = {
{ 0.000f, 1.000f, 0.500f, 1.000f},
{-0.200f, 0.600f, 0.400f, 0.800f},
{ 0.200f, 0.600f, 0.600f, 0.800f},
{-0.400f, 0.200f, 0.300f, 0.600f},
{ 0.000f, 0.200f, 0.500f, 0.600f},
{ 0.400f, 0.200f, 0.300f, 0.600f},
{-0.600f, -0.200f, 0.200f, 0.400f},
{-0.200f, -0.200f, 0.400f, 0.400f},
{ 0.200f, -0.200f, 0.600f, 0.400f},
{ 0.600f, -0.200f, 0.800f, 0.400f},
{-0.800f, -0.600f, 0.100f, 0.200f},
{-0.400f, -0.600f, 0.300f, 0.200f},
{ 0.000f, -0.600f, 0.500f, 0.200f},
{ 0.400f, -0.600f, 0.700f, 0.200f},
{ 0.800f, -0.600f, 0.900f, 0.200f},
{-1.000f, -1.000f, 0.000f, 0.000f},
{-0.600f, -1.000f, 0.200f, 0.000f},
{-0.200f, -1.000f, 0.400f, 0.000f},
{ 0.200f, -1.000f, 0.600f, 0.000f},
{ 0.600f, -1.000f, 0.800f, 0.000f},
{ 1.000f, -1.000f, 1.000f, 0.000f}
};
rw::uint16 IndexedTriListIndices[45] = {
0, 1, 2,
1, 3, 4, 2, 4, 5,
3, 6, 7, 4, 7, 8, 5, 8, 9,
6, 10, 11, 7, 11, 12, 8, 12, 13, 9, 13, 14,
10, 15, 16, 11, 16, 17, 12, 17, 18, 13, 18, 19, 14, 19, 20
};
rw::RWDEVICE::Im2DVertex TriList[18];
rw::RWDEVICE::Im2DVertex IndexedTriList[21];
void
TriListCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 18; i++){
TriList[i].setScreenX(ScreenSize.x/2.0f + TriListData[i][0]*Scale);
TriList[i].setScreenY(ScreenSize.y/2.0f - TriListData[i][1]*Scale);
TriList[i].setScreenZ(rw::im2d::GetNearZ());
TriList[i].setRecipCameraZ(recipZ);
TriList[i].setU(TriListData[i][2], recipZ);
TriList[i].setV(TriListData[i][3], recipZ);
}
}
void
TriListSetColor(bool white)
{
int i;
rw::RGBA SolidColor1 = SolidBlue;
rw::RGBA SolidColor2 = SolidRed;
rw::RGBA SolidColor3 = SolidGreen;
rw::RGBA SolidColor4 = SolidYellow;
rw::RGBA SolidColor5 = SolidPurple;
rw::RGBA SolidColor6 = SolidCyan;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
SolidColor3 = SolidWhite;
SolidColor4 = SolidWhite;
SolidColor5 = SolidWhite;
SolidColor6 = SolidWhite;
}
for(i = 0; i < 3; i++)
TriList[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
for(; i < 6; i++)
TriList[i].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
for(; i < 9; i++)
TriList[i].setColor(SolidColor3.red, SolidColor3.green,
SolidColor3.blue, SolidColor3.alpha);
for(; i < 12; i++)
TriList[i].setColor(SolidColor4.red, SolidColor4.green,
SolidColor4.blue, SolidColor4.alpha);
for(; i < 15; i++)
TriList[i].setColor(SolidColor5.red, SolidColor5.green,
SolidColor5.blue, SolidColor5.alpha);
for(; i < 18; i++)
TriList[i].setColor(SolidColor6.red, SolidColor6.green,
SolidColor6.blue, SolidColor6.alpha);
}
void
TriListRender(void)
{
rw::im2d::RenderPrimitive(rw::PRIMTYPETRILIST, TriList, 18);
}
void
IndexedTriListCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 21; i++){
IndexedTriList[i].setScreenX(ScreenSize.x/2.0f + IndexedTriListData[i][0]*Scale);
IndexedTriList[i].setScreenY(ScreenSize.y/2.0f - IndexedTriListData[i][1]*Scale);
IndexedTriList[i].setScreenZ(rw::im2d::GetNearZ());
IndexedTriList[i].setRecipCameraZ(recipZ);
IndexedTriList[i].setU(IndexedTriListData[i][2], recipZ);
IndexedTriList[i].setV(IndexedTriListData[i][3], recipZ);
}
}
void
IndexedTriListSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidBlue;
if(white)
SolidColor1 = SolidWhite;
for(int i = 0; i < 21; i++)
IndexedTriList[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
IndexedTriListRender(void)
{
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST,
IndexedTriList, 21, IndexedTriListIndices, 45);
}

130
vendor/librw/tools/im2d/tristrip.cpp vendored Normal file
View file

@ -0,0 +1,130 @@
#include <rw.h>
#include <skeleton.h>
#include "im2d.h"
float TriStripData[18][4] = {
{ 0.000f, 1.000f, 0.500f, 1.000f},
{ 0.000f, 0.500f, 0.500f, 0.750f},
{ 0.707f, 0.707f, 0.853f, 0.853f},
{ 0.354f, 0.354f, 0.677f, 0.677f},
{ 1.000f, 0.000f, 1.000f, 0.500f},
{ 0.500f, 0.000f, 0.750f, 0.500f},
{ 0.707f, -0.707f, 0.853f, 0.147f},
{ 0.354f, -0.354f, 0.677f, 0.323f},
{ 0.000f, -1.000f, 0.500f, 0.000f},
{ 0.000f, -0.500f, 0.500f, 0.250f},
{-0.707f, -0.707f, 0.147f, 0.147f},
{-0.354f, -0.354f, 0.323f, 0.323f},
{-1.000f, 0.000f, 0.000f, 0.500f},
{-0.500f, 0.000f, 0.250f, 0.500f},
{-0.707f, 0.707f, 0.147f, 0.853f},
{-0.354f, 0.354f, 0.323f, 0.677f},
{ 0.000f, 1.000f, 0.500f, 1.000f},
{ 0.000f, 0.500f, 0.500f, 0.750f}
};
float IndexedTriStripData[16][4] = {
{ 0.000f, 1.000f, 0.500f, 1.000f},
{ 0.707f, 0.707f, 0.853f, 0.853f},
{ 1.000f, 0.000f, 1.000f, 0.500f},
{ 0.707f, -0.707f, 0.853f, 0.147f},
{ 0.000f, -1.000f, 0.500f, 0.000f},
{-0.707f, -0.707f, 0.147f, 0.147f},
{-1.000f, 0.000f, 0.000f, 0.500f},
{-0.707f, 0.707f, 0.147f, 0.853f},
{ 0.000f, 0.500f, 0.500f, 0.750f},
{ 0.354f, 0.354f, 0.677f, 0.677f},
{ 0.500f, 0.000f, 0.750f, 0.500f},
{ 0.354f, -0.354f, 0.677f, 0.323f},
{ 0.000f, -0.500f, 0.500f, 0.250f},
{-0.354f, -0.354f, 0.323f, 0.323f},
{-0.500f, 0.000f, 0.250f, 0.500f},
{-0.354f, 0.354f, 0.323f, 0.677f}
};
rw::uint16 IndexedTriStripIndices[18] = {
0, 8, 1, 9, 2, 10, 3, 11,
4, 12, 5, 13, 6, 14, 7, 15, 0, 8
};
rw::RWDEVICE::Im2DVertex TriStrip[18];
rw::RWDEVICE::Im2DVertex IndexedTriStrip[16];
void
TriStripCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 18; i++){
TriStrip[i].setScreenX(ScreenSize.x/2.0f + TriStripData[i][0]*Scale);
TriStrip[i].setScreenY(ScreenSize.y/2.0f - TriStripData[i][1]*Scale);
TriStrip[i].setScreenZ(rw::im2d::GetNearZ());
TriStrip[i].setRecipCameraZ(recipZ);
TriStrip[i].setU(TriStripData[i][2], recipZ);
TriStrip[i].setV(TriStripData[i][3], recipZ);
}
}
void
TriStripSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidPurple;
if(white)
SolidColor1 = SolidWhite;
for(int i = 0; i < 18; i++)
TriStrip[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
TriStripRender(void)
{
rw::im2d::RenderPrimitive(rw::PRIMTYPETRISTRIP, TriStrip, 18);
}
void
IndexedTriStripCreate(rw::Camera *camera)
{
float recipZ = 1.0f/camera->nearPlane;
for(int i = 0; i < 16; i++){
IndexedTriStrip[i].setScreenX(ScreenSize.x/2.0f + IndexedTriStripData[i][0]*Scale);
IndexedTriStrip[i].setScreenY(ScreenSize.y/2.0f - IndexedTriStripData[i][1]*Scale);
IndexedTriStrip[i].setScreenZ(rw::im2d::GetNearZ());
IndexedTriStrip[i].setRecipCameraZ(recipZ);
IndexedTriStrip[i].setU(IndexedTriStripData[i][2], recipZ);
IndexedTriStrip[i].setV(IndexedTriStripData[i][3], recipZ);
}
}
void
IndexedTriStripSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidCyan;
if(white)
SolidColor1 = SolidWhite;
for(int i = 0; i < 16; i++)
IndexedTriStrip[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
IndexedTriStripRender(void)
{
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRISTRIP,
IndexedTriStrip, 16, IndexedTriStripIndices, 18);
}

23
vendor/librw/tools/im3d/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,23 @@
add_executable(im3d WIN32
im3d.cpp
linelist.cpp
main.cpp
polyline.cpp
trifan.cpp
trilist.cpp
tristrip.cpp
)
target_link_libraries(im3d
PRIVATE
librw::skeleton
librw::librw
)
add_custom_command(
TARGET im3d POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:im3d>/files"
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/files" "$<TARGET_FILE_DIR:im3d>/files"
)
librw_platform_target(im3d)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

138
vendor/librw/tools/im3d/im3d.cpp vendored Normal file
View file

@ -0,0 +1,138 @@
#include <rw.h>
#include <skeleton.h>
#include "im3d.h"
bool Im3DColored = true;
bool Im3DTextured;
rw::int32 Im3DPrimType;
rw::RGBA SolidWhite = {255, 255, 255, 255};
rw::RGBA SolidBlack = {0, 0, 0, 255};
rw::RGBA SolidRed = {200, 64, 64, 255};
rw::RGBA SolidGreen = {64, 200, 64, 255};
rw::RGBA SolidBlue = {64, 64, 200, 255};
rw::RGBA SolidYellow = {200, 200, 64, 255};
rw::RGBA SolidPurple = {200, 64, 200, 255};
rw::RGBA SolidCyan = {64, 200, 200, 255};
rw::Matrix *Im3DMatrix;
rw::Texture *Im3DTexture;
void
Im3DInitialize(void)
{
Im3DMatrix = rw::Matrix::create();
assert(Im3DMatrix);
rw::Matrix *cameraMatrix = &Camera->getFrame()->matrix;
rw::V3d pos = rw::scale(cameraMatrix->at, 6.0f);
Im3DMatrix->rotate(&cameraMatrix->up, 30.0f);
Im3DMatrix->translate(&pos);
rw::Image::setSearchPath("files/");
Im3DTexture = rw::Texture::read("whiteash", nil);
LineListCreate();
LineListSetColor(!Im3DColored);
IndexedLineListCreate();
IndexedLineListSetColor(!Im3DColored);
PolyLineCreate();
PolyLineSetColor(!Im3DColored);
IndexedPolyLineCreate();
IndexedPolyLineSetColor(!Im3DColored);
TriListCreate();
TriListSetColor(!Im3DColored);
IndexedTriListCreate();
IndexedTriListSetColor(!Im3DColored);
TriStripCreate();
TriStripSetColor(!Im3DColored);
IndexedTriStripCreate();
IndexedTriStripSetColor(!Im3DColored);
TriFanCreate();
TriFanSetColor(!Im3DColored);
IndexedTriFanCreate();
IndexedTriFanSetColor(!Im3DColored);
}
void
Im3DTerminate(void)
{
if(Im3DMatrix){
Im3DMatrix->destroy();
Im3DMatrix = nil;
}
if(Im3DTexture){
Im3DTexture->destroy();
Im3DTexture = nil;
}
}
void
Im3DRender(void)
{
rw::SetRenderState(rw::ZTESTENABLE, 1);
rw::SetRenderState(rw::ZWRITEENABLE, 1);
rw::SetRenderState(rw::SRCBLEND, rw::BLENDONE);
rw::SetRenderState(rw::DESTBLEND, rw::BLENDZERO);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::FilterMode::LINEAR);
rw::SetRenderState(rw::CULLMODE, rw::CULLBACK);
rw::uint32 flags;
if(Im3DTextured){
rw::SetRenderStatePtr(rw::TEXTURERASTER, Im3DTexture->raster);
flags = rw::im3d::VERTEXUV | rw::im3d::ALLOPAQUE;
}else{
rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
flags = rw::im3d::ALLOPAQUE;
}
switch(Im3DPrimType){
case 0: LineListRender(Im3DMatrix, flags); break;
case 1: IndexedLineListRender(Im3DMatrix, flags); break;
case 2: PolyLineRender(Im3DMatrix, flags); break;
case 3: IndexedPolyLineRender(Im3DMatrix, flags); break;
case 4: TriListRender(Im3DMatrix, flags); break;
case 5: IndexedTriListRender(Im3DMatrix, flags); break;
case 6: TriStripRender(Im3DMatrix, flags); break;
case 7: IndexedTriStripRender(Im3DMatrix, flags); break;
case 8: TriFanRender(Im3DMatrix, flags); break;
case 9: IndexedTriFanRender(Im3DMatrix, flags); break;
}
}
void
Im3DRotate(float xAngle, float yAngle)
{
rw::Matrix *cameraMatrix = &Camera->getFrame()->matrix;
rw::V3d pos = Im3DMatrix->pos;
pos = rw::scale(pos, -1.0f);
Im3DMatrix->translate(&pos);
Im3DMatrix->rotate(&cameraMatrix->up, xAngle);
Im3DMatrix->rotate(&cameraMatrix->right, yAngle);
pos = rw::scale(pos, -1.0f);
Im3DMatrix->translate(&pos);
}
void
Im3DTranslateZ(float zDelta)
{
rw::Matrix *cameraMatrix = &Camera->getFrame()->matrix;
rw::V3d delta = rw::scale(cameraMatrix->at, zDelta);
Im3DMatrix->translate(&delta);
}

62
vendor/librw/tools/im3d/im3d.h vendored Normal file
View file

@ -0,0 +1,62 @@
extern rw::Camera *Camera;
extern bool Im3DColored;
extern bool Im3DTextured;
extern rw::int32 Im3DPrimType;
extern rw::RGBA SolidWhite;
extern rw::RGBA SolidBlack;
extern rw::RGBA SolidRed;
extern rw::RGBA SolidGreen;
extern rw::RGBA SolidBlue;
extern rw::RGBA SolidYellow;
extern rw::RGBA SolidPurple;
extern rw::RGBA SolidCyan;
void Im3DInitialize(void);
void Im3DTerminate(void);
void Im3DRender(void);
void Im3DRotate(float xAngle, float yAngle);
void Im3DTranslateZ(float zDelta);
void LineListCreate(void);
void LineListSetColor(bool white);
void LineListRender(rw::Matrix *transform, rw::uint32 transformFlags);
void IndexedLineListCreate(void);
void IndexedLineListSetColor(bool white);
void IndexedLineListRender(rw::Matrix *transform, rw::uint32 transformFlags);
void PolyLineCreate(void);
void PolyLineSetColor(bool white);
void PolyLineRender(rw::Matrix *transform, rw::uint32 transformFlags);
void IndexedPolyLineCreate(void);
void IndexedPolyLineSetColor(bool white);
void IndexedPolyLineRender(rw::Matrix *transform, rw::uint32 transformFlags);
void TriListCreate(void);
void TriListSetColor(bool white);
void TriListRender(rw::Matrix *transform, rw::uint32 transformFlags);
void IndexedTriListCreate(void);
void IndexedTriListSetColor(bool white);
void IndexedTriListRender(rw::Matrix *transform, rw::uint32 transformFlags);
void TriStripCreate(void);
void TriStripSetColor(bool white);
void TriStripRender(rw::Matrix *transform, rw::uint32 transformFlags);
void IndexedTriStripCreate(void);
void IndexedTriStripSetColor(bool white);
void IndexedTriStripRender(rw::Matrix *transform, rw::uint32 transformFlags);
void TriFanCreate(void);
void TriFanSetColor(bool white);
void TriFanRender(rw::Matrix *transform, rw::uint32 transformFlags);
void IndexedTriFanCreate(void);
void IndexedTriFanSetColor(bool white);
void IndexedTriFanRender(rw::Matrix *transform, rw::uint32 transformFlags);

176
vendor/librw/tools/im3d/linelist.cpp vendored Normal file
View file

@ -0,0 +1,176 @@
#include <rw.h>
#include <skeleton.h>
#include "im3d.h"
float LineListData[28][5] = {
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.000f, 1.000f, 0.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.000f, -1.000f, 0.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.000f, 0.000f, 1.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.000f, 0.000f, -1.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 1.000f, 0.000f, 0.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{-1.000f, 0.000f, 0.000f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.577f, 0.577f, 0.577f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.577f, -0.577f, 0.577f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{-0.577f, 0.577f, -0.577f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{-0.577f, -0.577f, -0.577f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.577f, -0.577f, -0.577f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.577f, 0.577f, -0.577f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{-0.577f, -0.577f, 0.577f, 1.000f, 1.000f},
{ 0.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{-0.577f, 0.577f, 0.577f, 1.000f, 1.000f}
};
float IndexedLineListData[18][5] = {
{ 0.000f, 1.000f, 0.000f, 0.000f, 0.000f},
{ 0.577f, 0.577f, 0.577f, 0.000f, 0.000f},
{ 0.577f, 0.577f, -0.577f, 0.000f, 0.000f},
{-0.577f, 0.577f, -0.577f, 0.000f, 0.000f},
{-0.577f, 0.577f, 0.577f, 0.000f, 0.000f},
{ 0.000f, 0.000f, 1.000f, 0.000f, 0.000f},
{ 0.707f, 0.000f, 0.707f, 0.000f, 0.000f},
{ 1.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{ 0.707f, 0.000f, -0.707f, 0.000f, 0.000f},
{ 0.000f, 0.000f, -1.000f, 0.000f, 0.000f},
{-0.707f, 0.000f, -0.707f, 0.000f, 0.000f},
{-1.000f, 0.000f, 0.000f, 0.000f, 0.000f},
{-0.707f, 0.000f, 0.707f, 0.000f, 0.000f},
{ 0.577f, -0.577f, 0.577f, 0.000f, 0.000f},
{ 0.577f, -0.577f, -0.577f, 0.000f, 0.000f},
{-0.577f, -0.577f, -0.577f, 0.000f, 0.000f},
{-0.577f, -0.577f, 0.577f, 0.000f, 0.000f},
{ 0.000f, -1.000f, 0.000f, 0.000f, 0.000f}
};
rw::uint16 IndexedLineListIndices[96] = {
0,1, 0,2, 0,3, 0,4, 1,2, 2,3, 3,4, 4,1,
1,5, 1,6, 1,7, 2,7, 2,8, 2,9, 3,9, 3,10, 3,11, 4,11, 4,12, 4,5,
5,6, 6,7, 7,8, 8,9, 9,10, 10,11, 11,12, 12,5,
13,5, 13,6, 13,7, 14,7, 14,8, 14,9, 15,9, 15,10, 15,11, 16,11, 16,12, 16,5,
17,13, 17,14, 17,15, 17,16, 13,14, 14,15, 15,16, 16,13
};
rw::RWDEVICE::Im3DVertex LineList[28];
rw::RWDEVICE::Im3DVertex IndexedLineList[18];
void
LineListCreate(void)
{
for(int i = 0; i < 28; i++){
LineList[i].setX(LineListData[i][0]);
LineList[i].setY(LineListData[i][1]);
LineList[i].setZ(LineListData[i][2]);
LineList[i].setU(LineListData[i][3]);
LineList[i].setV(LineListData[i][4]);
}
}
void
LineListSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidRed;
rw::RGBA SolidColor2 = SolidWhite;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
}
for(int i = 0; i < 28; i += 2){
LineList[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
LineList[i+1].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
}
}
void
LineListRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(LineList, 28, transform, transformFlags);
rw::im3d::RenderPrimitive(rw::PRIMTYPELINELIST);
rw::im3d::End();
}
void
IndexedLineListCreate(void)
{
for(int i = 0; i < 18; i++){
IndexedLineList[i].setX(IndexedLineListData[i][0]);
IndexedLineList[i].setY(IndexedLineListData[i][1]);
IndexedLineList[i].setZ(IndexedLineListData[i][2]);
IndexedLineList[i].setU(IndexedLineListData[i][3]);
IndexedLineList[i].setV(IndexedLineListData[i][4]);
}
}
void
IndexedLineListSetColor(bool white)
{
int i;
rw::RGBA SolidColor1 = SolidRed;
rw::RGBA SolidColor2 = SolidGreen;
rw::RGBA SolidColor3 = SolidBlue;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
SolidColor3 = SolidWhite;
}
IndexedLineList[0].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
for(i = 1; i < 5; i++)
IndexedLineList[i].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
for(; i < 13; i++)
IndexedLineList[i].setColor(SolidColor3.red, SolidColor3.green,
SolidColor3.blue, SolidColor3.alpha);
for(; i < 17; i++)
IndexedLineList[i].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
IndexedLineList[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
}
void
IndexedLineListRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(IndexedLineList, 18, transform, transformFlags);
rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPELINELIST, IndexedLineListIndices, 96);
rw::im3d::End();
}

268
vendor/librw/tools/im3d/main.cpp vendored Normal file
View file

@ -0,0 +1,268 @@
#include <rw.h>
#include <skeleton.h>
#include <assert.h>
#include "im3d.h"
rw::EngineOpenParams engineOpenParams;
rw::RGBA ForegroundColor = { 200, 200, 200, 255 };
rw::RGBA BackgroundColor = { 64, 64, 64, 0 };
rw::Camera *Camera;
rw::Charset *Charset;
float TimeDelta;
rw::Camera*
CreateCamera(void)
{
Camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
assert(Camera);
Camera->setNearPlane(0.1f);
Camera->setFarPlane(50.0f);
return Camera;
}
void
Initialize(void)
{
sk::globals.windowtitle = "Im3D 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);
Camera = CreateCamera();
Im3DInitialize();
ImGui_ImplRW_Init();
ImGui::StyleColorsClassic();
rw::Rect r;
r.x = 0;
r.y = 0;
r.w = sk::globals.width;
r.h = sk::globals.height;
sk::CameraSize(::Camera, &r, 0.5f, 4.0f/3.0f);
return true;
}
void
Terminate3D(void)
{
Im3DTerminate();
if(Camera){
Camera->destroy();
Camera = 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)
{
}
void
Gui(void)
{
static bool showWindow = true;
ImGui::Begin("Im2D", &showWindow);
ImGui::RadioButton("Line-list", &Im3DPrimType, 0);
ImGui::RadioButton("Line-list indexed", &Im3DPrimType, 1);
ImGui::RadioButton("Poly-line", &Im3DPrimType, 2);
ImGui::RadioButton("Poly-line indexed", &Im3DPrimType, 3);
ImGui::RadioButton("Tri-list", &Im3DPrimType, 4);
ImGui::RadioButton("Tri-list indexed", &Im3DPrimType, 5);
ImGui::RadioButton("Tri-strip", &Im3DPrimType, 6);
ImGui::RadioButton("Tri-strip indexed", &Im3DPrimType, 7);
ImGui::RadioButton("Tri-fan", &Im3DPrimType, 8);
ImGui::RadioButton("Tri-fan indexed", &Im3DPrimType, 9);
ImGui::NewLine();
ImGui::Checkbox("Textured", &Im3DTextured);
if(ImGui::Checkbox("Colored", &Im3DColored)){
LineListSetColor(!Im3DColored);
IndexedLineListSetColor(!Im3DColored);
PolyLineSetColor(!Im3DColored);
IndexedPolyLineSetColor(!Im3DColored);
TriListSetColor(!Im3DColored);
IndexedTriListSetColor(!Im3DColored);
TriStripSetColor(!Im3DColored);
IndexedTriStripSetColor(!Im3DColored);
TriFanSetColor(!Im3DColored);
IndexedTriFanSetColor(!Im3DColored);
}
ImGui::End();
}
void
Render(void)
{
Camera->clear(&BackgroundColor, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
Camera->beginUpdate();
ImGui_ImplRW_NewFrame(TimeDelta);
Im3DRender();
DisplayOnScreenInfo();
Gui();
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplRW_RenderDrawLists(ImGui::GetDrawData());
Camera->endUpdate();
Camera->showRaster(0);
}
void
Idle(float timeDelta)
{
TimeDelta = timeDelta;
Render();
}
int MouseX, MouseY;
int MouseDeltaX, MouseDeltaY;
int MouseButtons;
bool Rotate, Translate;
void
KeyUp(int key)
{
}
void
KeyDown(int key)
{
switch(key){
case sk::KEY_ESC:
sk::globals.quit = 1;
break;
}
}
void
MouseBtn(sk::MouseState *mouse)
{
MouseButtons = mouse->buttons;
Rotate = !!(MouseButtons&1);
Translate = !!(MouseButtons&4);
}
void
MouseMove(sk::MouseState *mouse)
{
MouseDeltaX = mouse->posx - MouseX;
MouseDeltaY = mouse->posy - MouseY;
MouseX = mouse->posx;
MouseY = mouse->posy;
if(Rotate)
Im3DRotate(MouseDeltaX, -MouseDeltaY);
if(Translate)
Im3DTranslateZ(-MouseDeltaY*0.1f);
}
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;
if(::Camera){
sk::CameraSize(::Camera, r, 0.5f, 4.0f/3.0f);
}
break;
case IDLE:
Idle(*(float*)param);
return EVENTPROCESSED;
}
return sk::EVENTNOTPROCESSED;
}

157
vendor/librw/tools/im3d/polyline.cpp vendored Normal file
View file

@ -0,0 +1,157 @@
#include <rw.h>
#include <skeleton.h>
#include "im3d.h"
float PolyLineData[21][5] = {
{ 0.000f, 1.000f, 1.000f, 0.500f, 1.000f},
{ 0.707f, 0.707f, 0.900f, 0.854f, 0.854f},
{ 1.000f, 0.000f, 0.800f, 1.000f, 0.500f},
{ 0.707f, -0.707f, 0.700f, 0.854f, 0.146f},
{ 0.000f, -1.000f, 0.600f, 0.500f, 0.000f},
{-0.707f, -0.707f, 0.500f, 0.146f, 0.146f},
{-1.000f, -0.000f, 0.400f, 0.000f, 0.500f},
{-0.707f, 0.707f, 0.300f, 0.146f, 0.854f},
{ 0.000f, 1.000f, 0.200f, 0.500f, 1.000f},
{ 0.707f, 0.707f, 0.100f, 0.854f, 0.854f},
{ 1.000f, 0.000f, 0.000f, 1.000f, 0.500f},
{ 0.707f, -0.707f, -0.100f, 0.854f, 0.146f},
{ 0.000f, -1.000f, -0.200f, 0.500f, 0.000f},
{-0.707f, -0.707f, -0.300f, 0.146f, 0.146f},
{-1.000f, -0.000f, -0.400f, 0.000f, 0.500f},
{-0.707f, 0.707f, -0.500f, 0.146f, 0.854f},
{ 0.000f, 1.000f, -0.600f, 0.500f, 1.000f},
{ 0.707f, 0.707f, -0.700f, 0.854f, 0.854f},
{ 1.000f, 0.000f, -0.800f, 1.000f, 0.500f},
{ 0.707f, -0.707f, -0.900f, 0.854f, 0.146f},
{ 0.000f, -1.000f, -1.000f, 0.500f, 0.000f}
};
float IndexedPolyLineData[8][5] = {
{ 1.000f, 1.000f, 1.000f, 1.000f, 0.000f},
{-1.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{-1.000f, -1.000f, 1.000f, 0.500f, 1.000f},
{ 1.000f, -1.000f, 1.000f, 0.500f, 0.000f},
{ 1.000f, 1.000f, -1.000f, 0.500f, 0.000f},
{-1.000f, 1.000f, -1.000f, 0.500f, 1.000f},
{-1.000f, -1.000f, -1.000f, 0.000f, 1.000f},
{ 1.000f, -1.000f, -1.000f, 0.000f, 0.000f}
};
rw::uint16 IndexedPolyLineIndices[25] = {
0, 1, 2, 3, 0, 2, 6, 5, 1, 3, 7, 4, 0, 5, 4, 6, 1, 4, 3, 6, 7, 5, 2, 7, 0
};
rw::RWDEVICE::Im3DVertex PolyLine[21];
rw::RWDEVICE::Im3DVertex IndexedPolyLine[8];
void
PolyLineCreate(void)
{
for(int i = 0; i < 21; i++){
PolyLine[i].setX(PolyLineData[i][0]);
PolyLine[i].setY(PolyLineData[i][1]);
PolyLine[i].setZ(PolyLineData[i][2]);
PolyLine[i].setU(PolyLineData[i][3]);
PolyLine[i].setV(PolyLineData[i][4]);
}
}
void
PolyLineSetColor(bool white)
{
int i;
rw::RGBA SolidColor1 = SolidRed;
rw::RGBA SolidColor2 = SolidGreen;
rw::RGBA SolidColor3 = SolidBlue;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
SolidColor3 = SolidWhite;
}
for(i = 0; i < 7; i++)
PolyLine[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
for(; i < 14; i++)
PolyLine[i].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
for(; i < 21; i++)
PolyLine[i].setColor(SolidColor3.red, SolidColor3.green,
SolidColor3.blue, SolidColor3.alpha);
}
void
PolyLineRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(PolyLine, 21, transform, transformFlags);
rw::im3d::RenderPrimitive(rw::PRIMTYPEPOLYLINE);
rw::im3d::End();
}
void
IndexedPolyLineCreate(void)
{
for(int i = 0; i < 8; i++){
IndexedPolyLine[i].setX(IndexedPolyLineData[i][0]);
IndexedPolyLine[i].setY(IndexedPolyLineData[i][1]);
IndexedPolyLine[i].setZ(IndexedPolyLineData[i][2]);
IndexedPolyLine[i].setU(IndexedPolyLineData[i][3]);
IndexedPolyLine[i].setV(IndexedPolyLineData[i][4]);
}
}
void
IndexedPolyLineSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidRed;
rw::RGBA SolidColor2 = SolidYellow;
rw::RGBA SolidColor3 = SolidBlack;
rw::RGBA SolidColor4 = SolidPurple;
rw::RGBA SolidColor5 = SolidGreen;
rw::RGBA SolidColor6 = SolidCyan;
rw::RGBA SolidColor7 = SolidBlue;
rw::RGBA SolidColor8 = SolidWhite;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
SolidColor3 = SolidWhite;
SolidColor4 = SolidWhite;
SolidColor5 = SolidWhite;
SolidColor6 = SolidWhite;
SolidColor7 = SolidWhite;
SolidColor8 = SolidWhite;
}
IndexedPolyLine[0].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
IndexedPolyLine[1].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
IndexedPolyLine[2].setColor(SolidColor3.red, SolidColor3.green,
SolidColor3.blue, SolidColor3.alpha);
IndexedPolyLine[3].setColor(SolidColor4.red, SolidColor4.green,
SolidColor4.blue, SolidColor4.alpha);
IndexedPolyLine[4].setColor(SolidColor5.red, SolidColor5.green,
SolidColor5.blue, SolidColor5.alpha);
IndexedPolyLine[5].setColor(SolidColor6.red, SolidColor6.green,
SolidColor6.blue, SolidColor6.alpha);
IndexedPolyLine[6].setColor(SolidColor7.red, SolidColor7.green,
SolidColor7.blue, SolidColor7.alpha);
IndexedPolyLine[7].setColor(SolidColor8.red, SolidColor8.green,
SolidColor8.blue, SolidColor8.alpha);
}
void
IndexedPolyLineRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(IndexedPolyLine, 8, transform, transformFlags);
rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPEPOLYLINE, IndexedPolyLineIndices, 25);
rw::im3d::End();
}

152
vendor/librw/tools/im3d/trifan.cpp vendored Normal file
View file

@ -0,0 +1,152 @@
#include <rw.h>
#include <skeleton.h>
#include "im3d.h"
float TriFanData[34][5] = {
{ 0.000f, 0.000f, -1.000f, 0.500f, 0.500f},
{ 0.000f, 1.000f, 0.000f, 0.500f, 1.000f},
{ 0.383f, 0.924f, 0.000f, 0.691f, 0.962f},
{ 0.707f, 0.707f, 0.000f, 0.854f, 0.854f},
{ 0.924f, 0.383f, 0.000f, 0.962f, 0.691f},
{ 1.000f, 0.000f, 0.000f, 1.000f, 0.500f},
{ 0.924f, -0.383f, 0.000f, 0.962f, 0.309f},
{ 0.707f, -0.707f, 0.000f, 0.854f, 0.146f},
{ 0.383f, -0.924f, 0.000f, 0.691f, 0.038f},
{ 0.000f, -1.000f, 0.000f, 0.500f, 0.000f},
{-0.383f, -0.924f, 0.000f, 0.309f, 0.038f},
{-0.707f, -0.707f, 0.000f, 0.146f, 0.146f},
{-0.924f, -0.383f, 0.000f, 0.038f, 0.309f},
{-1.000f, -0.000f, 0.000f, 0.000f, 0.500f},
{-0.924f, 0.383f, 0.000f, 0.038f, 0.691f},
{-0.707f, 0.707f, 0.000f, 0.146f, 0.854f},
{-0.383f, 0.924f, 0.000f, 0.309f, 0.962f},
{ 0.000f, 1.000f, 0.000f, 0.500f, 1.000f},
{-0.383f, 0.924f, 0.000f, 0.309f, 0.962f},
{-0.707f, 0.707f, 0.000f, 0.146f, 0.854f},
{-0.924f, 0.383f, 0.000f, 0.038f, 0.691f},
{-1.000f, -0.000f, 0.000f, 0.000f, 0.500f},
{-0.924f, -0.383f, 0.000f, 0.038f, 0.309f},
{-0.707f, -0.707f, 0.000f, 0.146f, 0.146f},
{-0.383f, -0.924f, 0.000f, 0.309f, 0.038f},
{ 0.000f, -1.000f, 0.000f, 0.500f, 0.000f},
{ 0.383f, -0.924f, 0.000f, 0.691f, 0.038f},
{ 0.707f, -0.707f, 0.000f, 0.854f, 0.146f},
{ 0.924f, -0.383f, 0.000f, 0.962f, 0.309f},
{ 1.000f, 0.000f, 0.000f, 1.000f, 0.500f},
{ 0.924f, 0.383f, 0.000f, 0.962f, 0.691f},
{ 0.707f, 0.707f, 0.000f, 0.854f, 0.854f},
{ 0.383f, 0.924f, 0.000f, 0.691f, 0.962f},
{ 0.000f, 1.000f, 0.000f, 0.500f, 1.000f}
};
float IndexedTriFanData[17][5] = {
/* top */
{ 0.000f, 0.000f, -1.000f, 0.500f, 0.500f},
/* circle */
{ 0.000f, 1.000f, 0.000f, 0.500f, 1.000f},
{ 0.383f, 0.924f, 0.000f, 0.691f, 0.962f},
{ 0.707f, 0.707f, 0.000f, 0.854f, 0.854f},
{ 0.924f, 0.383f, 0.000f, 0.962f, 0.691f},
{ 1.000f, 0.000f, 0.000f, 1.000f, 0.500f},
{ 0.924f, -0.383f, 0.000f, 0.962f, 0.309f},
{ 0.707f, -0.707f, 0.000f, 0.854f, 0.146f},
{ 0.383f, -0.924f, 0.000f, 0.691f, 0.038f},
{ 0.000f, -1.000f, 0.000f, 0.500f, 0.000f},
{-0.383f, -0.924f, 0.000f, 0.309f, 0.038f},
{-0.707f, -0.707f, 0.000f, 0.146f, 0.146f},
{-0.924f, -0.383f, 0.000f, 0.038f, 0.309f},
{-1.000f, -0.000f, 0.000f, 0.000f, 0.500f},
{-0.924f, 0.383f, 0.000f, 0.038f, 0.691f},
{-0.707f, 0.707f, 0.000f, 0.146f, 0.854f},
{-0.383f, 0.924f, 0.000f, 0.309f, 0.962f}
};
rw::uint16 IndexedTriFanIndices[34] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1,
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
};
rw::RWDEVICE::Im3DVertex TriFan[34];
rw::RWDEVICE::Im3DVertex IndexedTriFan[17];
void
TriFanCreate(void)
{
for(int i = 0; i < 34; i++){
TriFan[i].setX(TriFanData[i][0]);
TriFan[i].setY(TriFanData[i][1]);
TriFan[i].setZ(TriFanData[i][2]);
TriFan[i].setU(TriFanData[i][3]);
TriFan[i].setV(TriFanData[i][4]);
}
}
void
TriFanSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidYellow;
rw::RGBA SolidColor2 = SolidBlue;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
}
TriFan[0].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
for(int i = 1; i < 34; i++)
TriFan[i].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
}
void
TriFanRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(TriFan, 34, transform, transformFlags);
rw::im3d::RenderPrimitive(rw::PRIMTYPETRIFAN);
rw::im3d::End();
}
void
IndexedTriFanCreate(void)
{
for(int i = 0; i < 17; i++){
IndexedTriFan[i].setX(IndexedTriFanData[i][0]);
IndexedTriFan[i].setY(IndexedTriFanData[i][1]);
IndexedTriFan[i].setZ(IndexedTriFanData[i][2]);
IndexedTriFan[i].setU(IndexedTriFanData[i][3]);
IndexedTriFan[i].setV(IndexedTriFanData[i][4]);
}
}
void
IndexedTriFanSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidGreen;
rw::RGBA SolidColor2 = SolidBlack;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
}
IndexedTriFan[0].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
for(int i = 1; i < 17; i++)
IndexedTriFan[i].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
}
void
IndexedTriFanRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(IndexedTriFan, 17, transform, transformFlags);
rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRIFAN, IndexedTriFanIndices, 34);
rw::im3d::End();
}

202
vendor/librw/tools/im3d/trilist.cpp vendored Normal file
View file

@ -0,0 +1,202 @@
#include <rw.h>
#include <skeleton.h>
#include "im3d.h"
float TriListData[36][5] = {
/* front */
{ 1.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{-1.000f, -1.000f, 1.000f, 0.000f, 0.000f},
{ 1.000f, -1.000f, 1.000f, 1.000f, 0.000f},
{ 1.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{-1.000f, 1.000f, 1.000f, 0.000f, 1.000f},
{-1.000f, -1.000f, 1.000f, 0.000f, 0.000f},
/* back */
{-1.000f, -1.000f, -1.000f, 1.000f, 1.000f},
{-1.000f, 1.000f, -1.000f, 1.000f, 0.000f},
{ 1.000f, 1.000f, -1.000f, 0.000f, 0.000f},
{-1.000f, -1.000f, -1.000f, 1.000f, 1.000f},
{ 1.000f, 1.000f, -1.000f, 0.000f, 0.000f},
{ 1.000f, -1.000f, -1.000f, 0.000f, 1.000f},
/* top */
{ 1.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{ 1.000f, 1.000f, -1.000f, 1.000f, 0.000f},
{-1.000f, 1.000f, -1.000f, 0.000f, 0.000f},
{ 1.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{-1.000f, 1.000f, -1.000f, 0.000f, 0.000f},
{-1.000f, 1.000f, 1.000f, 0.000f, 1.000f},
/* bottom */
{-1.000f, -1.000f, -1.000f, 1.000f, 1.000f},
{ 1.000f, -1.000f, 1.000f, 0.000f, 0.000f},
{-1.000f, -1.000f, 1.000f, 1.000f, 0.000f},
{-1.000f, -1.000f, -1.000f, 1.000f, 1.000f},
{ 1.000f, -1.000f, -1.000f, 0.000f, 1.000f},
{ 1.000f, -1.000f, 1.000f, 0.000f, 0.000f},
/* left */
{-1.000f, -1.000f, -1.000f, 1.000f, 1.000f},
{-1.000f, 1.000f, 1.000f, 0.000f, 0.000f},
{-1.000f, 1.000f, -1.000f, 1.000f, 0.000f},
{-1.000f, -1.000f, -1.000f, 1.000f, 1.000f},
{-1.000f, -1.000f, 1.000f, 0.000f, 1.000f},
{-1.000f, 1.000f, 1.000f, 0.000f, 0.000f},
/* right */
{ 1.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{ 1.000f, -1.000f, 1.000f, 1.000f, 0.000f},
{ 1.000f, -1.000f, -1.000f, 0.000f, 0.000f},
{ 1.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{ 1.000f, -1.000f, -1.000f, 0.000f, 0.000f},
{ 1.000f, 1.000f, -1.000f, 0.000f, 1.000f}
};
float IndexedTriListData[8][5] = {
{ 1.000f, 1.000f, 1.000f, 1.000f, 0.000f},
{-1.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{-1.000f, -1.000f, 1.000f, 0.500f, 1.000f},
{ 1.000f, -1.000f, 1.000f, 0.500f, 0.000f},
{ 1.000f, 1.000f, -1.000f, 0.500f, 0.000f},
{-1.000f, 1.000f, -1.000f, 0.500f, 1.000f},
{-1.000f, -1.000f, -1.000f, 0.000f, 1.000f},
{ 1.000f, -1.000f, -1.000f, 0.000f, 0.000f}
};
rw::uint16 IndexedTriListIndices[36] = {
/* front */
0, 1, 3, 1, 2, 3,
/* back */
7, 5, 4, 5, 7, 6,
/* left */
6, 2, 1, 1, 5, 6,
/* right */
0, 3, 4, 4, 3, 7,
/* top */
1, 0, 4, 1, 4, 5,
/* bottom */
2, 6, 3, 6, 7, 3
};
rw::RWDEVICE::Im3DVertex TriList[36];
rw::RWDEVICE::Im3DVertex IndexedTriList[8];
void
TriListCreate(void)
{
for(int i = 0; i < 36; i++){
TriList[i].setX(TriListData[i][0]);
TriList[i].setY(TriListData[i][1]);
TriList[i].setZ(TriListData[i][2]);
TriList[i].setU(TriListData[i][3]);
TriList[i].setV(TriListData[i][4]);
}
}
void
TriListSetColor(bool white)
{
int i;
rw::RGBA SolidColor1 = SolidRed;
rw::RGBA SolidColor2 = SolidBlue;
rw::RGBA SolidColor3 = SolidGreen;
rw::RGBA SolidColor4 = SolidYellow;
rw::RGBA SolidColor5 = SolidCyan;
rw::RGBA SolidColor6 = SolidPurple;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
SolidColor3 = SolidWhite;
SolidColor4 = SolidWhite;
SolidColor5 = SolidWhite;
SolidColor6 = SolidWhite;
}
for(i = 0; i < 6; i++)
TriList[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
for(; i < 12; i++)
TriList[i].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
for(; i < 18; i++)
TriList[i].setColor(SolidColor3.red, SolidColor3.green,
SolidColor3.blue, SolidColor3.alpha);
for(; i < 24; i++)
TriList[i].setColor(SolidColor4.red, SolidColor4.green,
SolidColor4.blue, SolidColor4.alpha);
for(; i < 30; i++)
TriList[i].setColor(SolidColor5.red, SolidColor5.green,
SolidColor5.blue, SolidColor5.alpha);
for(; i < 36; i++)
TriList[i].setColor(SolidColor6.red, SolidColor6.green,
SolidColor6.blue, SolidColor6.alpha);
}
void
TriListRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(TriList, 36, transform, transformFlags);
rw::im3d::RenderPrimitive(rw::PRIMTYPETRILIST);
rw::im3d::End();
}
void
IndexedTriListCreate(void)
{
for(int i = 0; i < 8; i++){
IndexedTriList[i].setX(IndexedTriListData[i][0]);
IndexedTriList[i].setY(IndexedTriListData[i][1]);
IndexedTriList[i].setZ(IndexedTriListData[i][2]);
IndexedTriList[i].setU(IndexedTriListData[i][3]);
IndexedTriList[i].setV(IndexedTriListData[i][4]);
}
}
void
IndexedTriListSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidRed;
rw::RGBA SolidColor2 = SolidYellow;
rw::RGBA SolidColor3 = SolidBlack;
rw::RGBA SolidColor4 = SolidPurple;
rw::RGBA SolidColor5 = SolidGreen;
rw::RGBA SolidColor6 = SolidCyan;
rw::RGBA SolidColor7 = SolidBlue;
rw::RGBA SolidColor8 = SolidWhite;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
SolidColor3 = SolidWhite;
SolidColor4 = SolidWhite;
SolidColor5 = SolidWhite;
SolidColor6 = SolidWhite;
SolidColor7 = SolidWhite;
SolidColor8 = SolidWhite;
}
IndexedTriList[0].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
IndexedTriList[1].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
IndexedTriList[2].setColor(SolidColor3.red, SolidColor3.green,
SolidColor3.blue, SolidColor3.alpha);
IndexedTriList[3].setColor(SolidColor4.red, SolidColor4.green,
SolidColor4.blue, SolidColor4.alpha);
IndexedTriList[4].setColor(SolidColor5.red, SolidColor5.green,
SolidColor5.blue, SolidColor5.alpha);
IndexedTriList[5].setColor(SolidColor6.red, SolidColor6.green,
SolidColor6.blue, SolidColor6.alpha);
IndexedTriList[6].setColor(SolidColor7.red, SolidColor7.green,
SolidColor7.blue, SolidColor7.alpha);
IndexedTriList[7].setColor(SolidColor8.red, SolidColor8.green,
SolidColor8.blue, SolidColor8.alpha);
}
void
IndexedTriListRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(IndexedTriList, 8, transform, transformFlags);
rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, IndexedTriListIndices, 36);
rw::im3d::End();
}

169
vendor/librw/tools/im3d/tristrip.cpp vendored Normal file
View file

@ -0,0 +1,169 @@
#include <rw.h>
#include <skeleton.h>
#include "im3d.h"
float TriStripData[36][5] = {
{ 0.000f, 1.000f, -1.000f, 0.000f, 0.000f},
{ 0.000f, 1.000f, 1.000f, 0.000f, 1.000f},
{ 0.707f, 0.707f, -1.000f, 0.125f, 0.000f},
{ 0.707f, 0.707f, 1.000f, 0.125f, 1.000f},
{ 1.000f, 0.000f, -1.000f, 0.250f, 0.000f},
{ 1.000f, 0.000f, 1.000f, 0.250f, 1.000f},
{ 0.707f, -0.707f, -1.000f, 0.375f, 0.000f},
{ 0.707f, -0.707f, 1.000f, 0.375f, 1.000f},
{ 0.000f, -1.000f, -1.000f, 0.500f, 0.000f},
{ 0.000f, -1.000f, 1.000f, 0.500f, 1.000f},
{-0.707f, -0.707f, -1.000f, 0.625f, 0.000f},
{-0.707f, -0.707f, 1.000f, 0.625f, 1.000f},
{-1.000f, -0.000f, -1.000f, 0.750f, 0.000f},
{-1.000f, -0.000f, 1.000f, 0.750f, 1.000f},
{-0.707f, 0.707f, -1.000f, 0.875f, 0.000f},
{-0.707f, 0.707f, 1.000f, 0.875f, 1.000f},
{ 0.000f, 1.000f, -1.000f, 1.000f, 0.000f},
{ 0.000f, 1.000f, 1.000f, 1.000f, 1.000f},
{ 0.000f, 1.000f, 1.000f, 0.000f, 0.000f},
{ 0.000f, 1.000f, -1.000f, 0.000f, 1.000f},
{ 0.707f, 0.707f, 1.000f, 0.125f, 0.000f},
{ 0.707f, 0.707f, -1.000f, 0.125f, 1.000f},
{ 1.000f, 0.000f, 1.000f, 0.250f, 0.000f},
{ 1.000f, 0.000f, -1.000f, 0.250f, 1.000f},
{ 0.707f, -0.707f, 1.000f, 0.375f, 0.000f},
{ 0.707f, -0.707f, -1.000f, 0.375f, 1.000f},
{ 0.000f, -1.000f, 1.000f, 0.500f, 0.000f},
{ 0.000f, -1.000f, -1.000f, 0.500f, 1.000f},
{-0.707f, -0.707f, 1.000f, 0.625f, 0.000f},
{-0.707f, -0.707f, -1.000f, 0.625f, 1.000f},
{-1.000f, -0.000f, 1.000f, 0.750f, 0.000f},
{-1.000f, -0.000f, -1.000f, 0.750f, 1.000f},
{-0.707f, 0.707f, 1.000f, 0.875f, 0.000f},
{-0.707f, 0.707f, -1.000f, 0.875f, 1.000f},
{ 0.000f, 1.000f, 1.000f, 1.000f, 0.000f},
{ 0.000f, 1.000f, -1.000f, 1.000f, 1.000f}
};
float IndexedTriStripData[16][5] = {
{ 0.000f, 1.000f, 1.000f, 0.000f, 0.000f},
{ 0.707f, 0.707f, 1.000f, 0.250f, 0.000f},
{ 1.000f, 0.000f, 1.000f, 0.500f, 0.000f},
{ 0.707f, -0.707f, 1.000f, 0.750f, 0.000f},
{ 0.000f, -1.000f, 1.000f, 1.000f, 0.000f},
{-0.707f, -0.707f, 1.000f, 0.750f, 0.000f},
{-1.000f, -0.000f, 1.000f, 0.500f, 0.000f},
{-0.707f, 0.707f, 1.000f, 0.250f, 0.000f},
{ 0.000f, 1.000f, -1.000f, 0.000f, 1.000f},
{ 0.707f, 0.707f, -1.000f, 0.250f, 1.000f},
{ 1.000f, 0.000f, -1.000f, 0.500f, 1.000f},
{ 0.707f, -0.707f, -1.000f, 0.750f, 1.000f},
{ 0.000f, -1.000f, -1.000f, 1.000f, 1.000f},
{-0.707f, -0.707f, -1.000f, 0.750f, 1.000f},
{-1.000f, -0.000f, -1.000f, 0.500f, 1.000f},
{-0.707f, 0.707f, -1.000f, 0.250f, 1.000f},
};
rw::uint16 IndexedTriStripIndices[36] = {
0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 0, 8,
8, 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 8, 0
};
rw::RWDEVICE::Im3DVertex TriStrip[36];
rw::RWDEVICE::Im3DVertex IndexedTriStrip[16];
void
TriStripCreate(void)
{
for(int i = 0; i < 36; i++){
TriStrip[i].setX(TriStripData[i][0]);
TriStrip[i].setY(TriStripData[i][1]);
TriStrip[i].setZ(TriStripData[i][2]);
TriStrip[i].setU(TriStripData[i][3]);
TriStrip[i].setV(TriStripData[i][4]);
}
}
void
TriStripSetColor(bool white)
{
rw::RGBA SolidColor1 = SolidRed;
rw::RGBA SolidColor2 = SolidYellow;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
}
for(int i = 0; i < 36; i += 2){
TriStrip[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
TriStrip[i+1].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
}
}
void
TriStripRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(TriStrip, 36, transform, transformFlags);
rw::im3d::RenderPrimitive(rw::PRIMTYPETRISTRIP);
rw::im3d::End();
}
void
IndexedTriStripCreate(void)
{
for(int i = 0; i < 16; i++){
IndexedTriStrip[i].setX(IndexedTriStripData[i][0]);
IndexedTriStrip[i].setY(IndexedTriStripData[i][1]);
IndexedTriStrip[i].setZ(IndexedTriStripData[i][2]);
IndexedTriStrip[i].setU(IndexedTriStripData[i][3]);
IndexedTriStrip[i].setV(IndexedTriStripData[i][4]);
}
}
void
IndexedTriStripSetColor(bool white)
{
int i;
rw::RGBA SolidColor1 = SolidBlue;
rw::RGBA SolidColor2 = SolidGreen;
if(white){
SolidColor1 = SolidWhite;
SolidColor2 = SolidWhite;
}
for(i = 0; i < 8; i++)
IndexedTriStrip[i].setColor(SolidColor1.red, SolidColor1.green,
SolidColor1.blue, SolidColor1.alpha);
for(; i < 16; i++)
IndexedTriStrip[i].setColor(SolidColor2.red, SolidColor2.green,
SolidColor2.blue, SolidColor2.alpha);
}
void
IndexedTriStripRender(rw::Matrix *transform, rw::uint32 transformFlags)
{
rw::im3d::Transform(IndexedTriStrip, 16, transform, transformFlags);
rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRISTRIP, IndexedTriStripIndices, 36);
rw::im3d::End();
}

View file

@ -0,0 +1,17 @@
add_executable(imguitest WIN32
main.cpp
)
target_link_libraries(imguitest
PUBLIC
librw::skeleton
librw::librw
)
if(LIBRW_INSTALL)
install(TARGETS imguitest
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
endif()
librw_platform_target(imguitest INSTALL)

175
vendor/librw/tools/imguitest/main.cpp vendored Normal file
View file

@ -0,0 +1,175 @@
#include <rw.h>
#include <skeleton.h>
#include <assert.h>
rw::V3d zero = { 0.0f, 0.0f, 0.0f };
struct SceneGlobals {
rw::World *world;
rw::Camera *camera;
} Scene;
rw::EngineOpenParams engineOpenParams;
void
Init(void)
{
sk::globals.windowtitle = "ImGui test";
sk::globals.width = 1280;
sk::globals.height = 800;
sk::globals.quit = 0;
}
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;
}
bool
InitRW(void)
{
// rw::platform = rw::PLATFORM_D3D8;
if(!sk::InitRW())
return false;
Scene.world = rw::World::create();
rw::Light *ambient = rw::Light::create(rw::Light::AMBIENT);
ambient->setColor(0.2f, 0.2f, 0.2f);
Scene.world->addLight(ambient);
rw::V3d xaxis = { 1.0f, 0.0f, 0.0f };
rw::Light *direct = rw::Light::create(rw::Light::DIRECTIONAL);
direct->setColor(0.8f, 0.8f, 0.8f);
direct->setFrame(rw::Frame::create());
direct->getFrame()->rotate(&xaxis, 180.0f, rw::COMBINEREPLACE);
Scene.world->addLight(direct);
Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
Scene.world->addCamera(Scene.camera);
ImGui_ImplRW_Init();
ImGui::StyleColorsClassic();
return true;
}
void
Draw(float timeDelta)
{
static bool show_demo_window = true;
static bool show_another_window = false;
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
rw::RGBA clearcol = rw::makeRGBA(clear_color.x*255, clear_color.y*255, clear_color.z*255, clear_color.w*255);
Scene.camera->clear(&clearcol, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
Scene.camera->beginUpdate();
ImGui_ImplRW_NewFrame(timeDelta);
// 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
{
static float f = 0.0f;
ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if(ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
show_demo_window ^= 1;
if(ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
}
// 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if(show_another_window){
ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello from another window!");
ImGui::End();
}
// 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if(show_demo_window){
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
ImGui::ShowDemoWindow(&show_demo_window);
}
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplRW_RenderDrawLists(ImGui::GetDrawData());
Scene.camera->endUpdate();
Scene.camera->showRaster(0);
}
void
KeyUp(int key)
{
}
void
KeyDown(int key)
{
switch(key){
case sk::KEY_ESC:
sk::globals.quit = 1;
break;
}
}
sk::EventStatus
AppEventHandler(sk::Event e, void *param)
{
using namespace sk;
Rect *r;
ImGuiEventHandler(e, param);
switch(e){
case INITIALIZE:
Init();
return EVENTPROCESSED;
case RWINITIALIZE:
return ::InitRW() ? EVENTPROCESSED : EVENTERROR;
case PLUGINATTACH:
return attachPlugins() ? EVENTPROCESSED : EVENTERROR;
case KEYDOWN:
KeyDown(*(int*)param);
return EVENTPROCESSED;
case KEYUP:
KeyUp(*(int*)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;
// TODO: set aspect ratio
if(Scene.camera)
sk::CameraSize(Scene.camera, r);
break;
case IDLE:
Draw(*(float*)param);
return EVENTPROCESSED;
}
return sk::EVENTNOTPROCESSED;
}

View file

@ -0,0 +1,18 @@
add_executable(lights WIN32
main.cpp
lights.cpp
)
target_link_libraries(lights
PRIVATE
librw::skeleton
librw::librw
)
add_custom_command(
TARGET lights POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:lights>/files"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/checker.dff" "$<TARGET_FILE_DIR:lights>"
)
librw_platform_target(lights)

BIN
vendor/librw/tools/lights/checker.dff vendored Normal file

Binary file not shown.

463
vendor/librw/tools/lights/lights.cpp vendored Normal file
View file

@ -0,0 +1,463 @@
#include <rw.h>
#include <skeleton.h>
#include "main.h"
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();
}
(*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;
}
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);
}

37
vendor/librw/tools/lights/lights.h vendored Normal file
View file

@ -0,0 +1,37 @@
extern rw::Light *BaseAmbientLight;
extern bool BaseAmbientLightOn;
extern rw::Light *CurrentLight;
extern rw::Light *AmbientLight;
extern rw::Light *PointLight;
extern rw::Light *DirectLight;
extern rw::Light *SpotLight;
extern rw::Light *SpotSoftLight;
extern float LightRadius;
extern float LightConeAngle;
extern rw::RGBAf LightColor;
extern bool LightOn;
extern bool LightDrawOn;
extern rw::V3d LightPos;
extern rw::int32 LightTypeIndex;
extern rw::BBox RoomBBox;
rw::Light *CreateBaseAmbientLight(void);
rw::Light *CreateAmbientLight(void);
rw::Light *CreateDirectLight(void);
rw::Light *CreatePointLight(void);
rw::Light *CreateSpotLight(void);
rw::Light *CreateSpotSoftLight(void);
void LightsDestroy(void);
void LightsUpdate(void);
void DrawCurrentLight(void);
void LightRotate(float xAngle, float yAngle);
void LightTranslateXY(float xDelta, float yDelta);
void LightTranslateZ(float zDelta);

396
vendor/librw/tools/lights/main.cpp vendored Normal file
View file

@ -0,0 +1,396 @@
#include <rw.h>
#include <skeleton.h>
#include <assert.h>
#include "main.h"
#include "lights.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::World *World;
rw::Camera *Camera;
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 };
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);
}
rw::Camera*
CreateCamera(rw::World *world)
{
rw::Camera *camera;
camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
assert(camera);
camera->setNearPlane(0.1f);
camera->setFarPlane(300.0f);
camera->setFOV(FOV, (float)sk::globals.width/sk::globals.height);
world->addCamera(camera);
return camera;
}
bool
CreateTestScene(rw::World *world)
{
rw::Clump *clump;
rw::StreamFile in;
const char *filename = "checker.dff";
if(in.open(filename, "rb") == NULL){
printf("couldn't open file\n");
return false;
}
if(!rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL))
return false;
clump = rw::Clump::streamRead(&in);
in.close();
if(clump == nil)
return false;
rw::Clump *clone;
rw::Frame *clumpFrame;
rw::V3d pos;
float zOffset = 75.0f;
// Bottom panel
clumpFrame = clump->getFrame();
clumpFrame->rotate(&Xaxis, 90.0f, rw::COMBINEREPLACE);
pos.x = 0.0f;
pos.y = -25.0f;
pos.z = zOffset;
clumpFrame->translate(&pos, rw::COMBINEPOSTCONCAT);
// only need to add once
world->addClump(clump);
// Top panel
clone = clump->clone();
clumpFrame = clone->getFrame();
clumpFrame->rotate(&Xaxis, -90.0f, rw::COMBINEREPLACE);
pos.x = 0.0f;
pos.y = 25.0f;
pos.z = zOffset;
clumpFrame->translate(&pos, rw::COMBINEPOSTCONCAT);
// Left panel
clone = clump->clone();
clumpFrame = clone->getFrame();
clumpFrame->rotate(&Xaxis, 0.0f, rw::COMBINEREPLACE);
clumpFrame->rotate(&Yaxis, 90.0f, rw::COMBINEPOSTCONCAT);
pos.x = 25.0f;
pos.y = 0.0f;
pos.z = zOffset;
clumpFrame->translate(&pos, rw::COMBINEPOSTCONCAT);
// Right panel
clone = clump->clone();
clumpFrame = clone->getFrame();
clumpFrame->rotate(&Xaxis, 0.0f, rw::COMBINEREPLACE);
clumpFrame->rotate(&Yaxis, -90.0f, rw::COMBINEPOSTCONCAT);
pos.x = -25.0f;
pos.y = 0.0f;
pos.z = zOffset;
clumpFrame->translate(&pos, rw::COMBINEPOSTCONCAT);
// Back panel
clone = clump->clone();
clumpFrame = clone->getFrame();
clumpFrame->rotate(&Xaxis, 0.0f, rw::COMBINEREPLACE);
pos.x = 0.0f;
pos.y = 0.0f;
pos.z = zOffset + 25.0f;
clumpFrame->translate(&pos, rw::COMBINEPOSTCONCAT);
// BBox
pos.x = 25.0f;
pos.y = 25.0f;
pos.z = zOffset - 25.0f;
RoomBBox.initialize(&pos);
pos.x = -25.0f;
pos.y = -25.0f;
pos.z = zOffset + 25.0f;
RoomBBox.addPoint(&pos);
return 1;
}
void
Initialize(void)
{
sk::globals.windowtitle = "Lights example";
sk::globals.width = 1280;
sk::globals.height = 800;
sk::globals.quit = 0;
}
bool
Initialize3D(void)
{
if(!sk::InitRW())
return false;
World = CreateWorld();
BaseAmbientLight = CreateBaseAmbientLight();
AmbientLight = CreateAmbientLight();
DirectLight = CreateDirectLight();
PointLight = CreatePointLight();
SpotLight = CreateSpotLight();
SpotSoftLight = CreateSpotSoftLight();
Camera = CreateCamera(World);
CreateTestScene(World);
ImGui_ImplRW_Init();
ImGui::StyleColorsClassic();
return true;
}
void
Terminate3D(void)
{
FORLIST(lnk, World->clumps){
rw::Clump *clump = rw::Clump::fromWorld(lnk);
World->removeClump(clump);
clump->destroy();
}
if(Camera){
World->removeCamera(Camera);
sk::CameraDestroy(Camera);
Camera = nil;
}
LightsDestroy();
if(World){
World->destroy();
World = 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
Gui(void)
{
// ImGui::ShowDemoWindow(nil);
static bool showLightWindow = true;
ImGui::Begin("Lights", &showLightWindow);
ImGui::Checkbox("Light", &LightOn);
ImGui::Checkbox("Draw Light", &LightDrawOn);
if(ImGui::Checkbox("Base Ambient", &BaseAmbientLightOn)){
if(BaseAmbientLightOn){
if(BaseAmbientLight->world == nil)
World->addLight(BaseAmbientLight);
}else{
if(BaseAmbientLight->world)
World->removeLight(BaseAmbientLight);
}
}
ImGui::RadioButton("Ambient Light", &LightTypeIndex, 0);
ImGui::RadioButton("Point Light", &LightTypeIndex, 1);
ImGui::RadioButton("Directional Light", &LightTypeIndex, 2);
ImGui::RadioButton("Spot Light", &LightTypeIndex, 3);
ImGui::RadioButton("Soft Spot Light", &LightTypeIndex, 4);
ImGui::ColorEdit3("Color", (float*)&LightColor);
float radAngle = LightConeAngle/180.0f*M_PI;
ImGui::SliderAngle("Cone angle", &radAngle, 0.0f, 180.0f);
LightConeAngle = radAngle/M_PI*180.0f;
ImGui::SliderFloat("Radius", &LightRadius, 0.1f, 500.0f);
ImGui::End();
}
void
Render(float timeDelta)
{
Camera->clear(&BackgroundColor, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
Camera->beginUpdate();
ImGui_ImplRW_NewFrame(timeDelta);
World->render();
if(LightDrawOn && CurrentLight)
DrawCurrentLight();
Gui();
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplRW_RenderDrawLists(ImGui::GetDrawData());
Camera->endUpdate();
Camera->showRaster(0);
}
void
Idle(float timeDelta)
{
LightsUpdate();
Render(timeDelta);
}
int MouseX, MouseY;
int MouseDeltaX, MouseDeltaY;
int MouseButtons;
int CtrlDown;
bool RotateLight;
bool TranslateLightXY;
bool TranslateLightZ;
void
KeyUp(int key)
{
switch(key){
case sk::KEY_LCTRL:
case sk::KEY_RCTRL:
CtrlDown = 0;
break;
}
}
void
KeyDown(int key)
{
switch(key){
case sk::KEY_LCTRL:
case sk::KEY_RCTRL:
CtrlDown = 1;
break;
case sk::KEY_ESC:
sk::globals.quit = 1;
break;
}
}
void
MouseBtn(sk::MouseState *mouse)
{
MouseButtons = mouse->buttons;
RotateLight = !CtrlDown && !!(MouseButtons&1);
TranslateLightXY = CtrlDown && !!(MouseButtons&1);
TranslateLightZ = CtrlDown && !!(MouseButtons&4);
}
void
MouseMove(sk::MouseState *mouse)
{
MouseDeltaX = mouse->posx - MouseX;
MouseDeltaY = mouse->posy - MouseY;
MouseX = mouse->posx;
MouseY = mouse->posy;
if(RotateLight)
LightRotate(-MouseDeltaX, MouseDeltaY);
if(TranslateLightXY)
LightTranslateXY(-MouseDeltaX*0.1f, -MouseDeltaY*0.1f);
if(TranslateLightZ)
LightTranslateZ(-MouseDeltaY*0.1f);
}
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;
if(::Camera){
sk::CameraSize(::Camera, r);
::Camera->setFOV(FOV, (float)sk::globals.width/sk::globals.height);
}
break;
case IDLE:
Idle(*(float*)param);
return EVENTPROCESSED;
}
return sk::EVENTNOTPROCESSED;
}

7
vendor/librw/tools/lights/main.h vendored Normal file
View file

@ -0,0 +1,7 @@
extern rw::World *World;
extern rw::Camera *Camera;
extern rw::V3d Xaxis;
extern rw::V3d Yaxis;
extern rw::V3d Zaxis;

View file

@ -0,0 +1,22 @@
add_executable(playground WIN32
camera.cpp
font.cpp
main.cpp
ras_test.cpp
splines.cpp
tl_tests.cpp
)
target_link_libraries(playground
PRIVATE
librw::skeleton
librw::librw
)
add_custom_command(
TARGET playground POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:playground>/files"
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/files" "$<TARGET_FILE_DIR:playground>/files"
)
librw_platform_target(playground)

134
vendor/librw/tools/playground/camera.cpp vendored Normal file
View file

@ -0,0 +1,134 @@
#include <cstdio>
#include <cassert>
#include <rw.h>
#define PI 3.14159265359f
#include "camera.h"
using rw::Quat;
using rw::V3d;
void
Camera::update(void)
{
if(m_rwcam){
m_rwcam->setNearPlane(m_near);
m_rwcam->setFarPlane(m_far);
m_rwcam->setFOV(m_fov, m_aspectRatio);
rw::Frame *f = m_rwcam->getFrame();
if(f){
V3d forward = normalize(sub(m_target, m_position));
V3d left = normalize(cross(m_up, forward));
V3d nup = cross(forward, left);
f->matrix.right = left; // lol
f->matrix.up = nup;
f->matrix.at = forward;
f->matrix.pos = m_position;
f->matrix.optimize();
f->updateObjects();
}
}
}
void
Camera::setTarget(V3d target)
{
m_position = sub(m_position, sub(m_target, target));
m_target = target;
}
float
Camera::getHeading(void)
{
V3d dir = sub(m_target, m_position);
float a = atan2(dir.y, dir.x)-PI/2.0f;
return m_localup.z < 0.0f ? a-PI : a;
}
void
Camera::turn(float yaw, float pitch)
{
V3d dir = sub(m_target, m_position);
Quat r = Quat::rotation(yaw, rw::makeV3d(0.0f, 0.0f, 1.0f));
dir = rotate(dir, r);
m_localup = rotate(m_localup, r);
V3d right = normalize(cross(dir, m_localup));
r = Quat::rotation(pitch, right);
dir = rotate(dir, r);
m_localup = normalize(cross(right, dir));
if(m_localup.z >= 0.0) m_up.z = 1.0;
else m_up.z = -1.0f;
m_target = add(m_position, dir);
}
void
Camera::orbit(float yaw, float pitch)
{
V3d dir = sub(m_target, m_position);
Quat r = Quat::rotation(yaw, rw::makeV3d(0.0f, 0.0f, 1.0f));
dir = rotate(dir, r);
m_localup = rotate(m_localup, r);
V3d right = normalize(cross(dir, m_localup));
r = Quat::rotation(-pitch, right);
dir = rotate(dir, r);
m_localup = normalize(cross(right, dir));
if(m_localup.z >= 0.0) m_up.z = 1.0;
else m_up.z = -1.0f;
m_position = sub(m_target, dir);
}
void
Camera::dolly(float dist)
{
V3d dir = setlength(sub(m_target, m_position), dist);
m_position = add(m_position, dir);
m_target = add(m_target, dir);
}
void
Camera::zoom(float dist)
{
V3d dir = sub(m_target, m_position);
float curdist = length(dir);
if(dist >= curdist)
dist = curdist-0.01f;
dir = setlength(dir, dist);
m_position = add(m_position, dir);
}
void
Camera::pan(float x, float y)
{
V3d dir = normalize(sub(m_target, m_position));
V3d right = normalize(cross(dir, m_up));
V3d localup = normalize(cross(right, dir));
dir = add(scale(right, x), scale(localup, y));
m_position = add(m_position, dir);
m_target = add(m_target, dir);
}
float
Camera::distanceTo(V3d v)
{
return length(sub(m_position, v));
}
Camera::Camera()
{
m_position.set(0.0f, 6.0f, 0.0f);
m_target.set(0.0f, 0.0f, 0.0f);
m_up.set(0.0f, 0.0f, 1.0f);
m_localup = m_up;
m_fov = 70.0f;
m_aspectRatio = 1.0f;
m_near = 0.1f;
m_far = 100.0f;
m_rwcam = NULL;
}

26
vendor/librw/tools/playground/camera.h vendored Normal file
View file

@ -0,0 +1,26 @@
class Camera
{
public:
rw::Camera *m_rwcam;
rw::V3d m_position;
rw::V3d m_target;
rw::V3d m_up;
rw::V3d m_localup;
float m_fov, m_aspectRatio;
float m_near, m_far;
void setTarget(rw::V3d target);
float getHeading(void);
void turn(float yaw, float pitch);
void orbit(float yaw, float pitch);
void dolly(float dist);
void zoom(float dist);
void pan(float x, float y);
void update(void);
float distanceTo(rw::V3d v);
Camera(void);
};

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

181
vendor/librw/tools/playground/font.cpp vendored Normal file
View file

@ -0,0 +1,181 @@
#include <rw.h>
#include <skeleton.h>
using namespace rw;
struct Font
{
Texture *tex;
int32 glyphwidth, glyphheight;
int32 numglyphs;
};
Font vga = { nil, 8, 16, 256 };
Font bios = { nil, 8, 8, 256 };
Font *curfont = &bios;
#define NUMCHARS 100
uint16 indices[NUMCHARS*6];
RWDEVICE::Im2DVertex vertices[NUMCHARS*4];
int32 curVert;
int32 curIndex;
void
printScreen(const char *s, float32 x, float32 y)
{
char c;
Camera *cam;
RWDEVICE::Im2DVertex *vert;
uint16 *ix;
curVert = 0;
curIndex = 0;
float32 u, v, du, dv;
float recipZ;
cam = (Camera*)engine->currentCamera;
vert = &vertices[curVert];
ix = &indices[curIndex];
du = curfont->glyphwidth/(float32)curfont->tex->raster->width;
dv = curfont->glyphheight/(float32)curfont->tex->raster->height;
recipZ = 1.0f/cam->nearPlane;
while(c = *s){
if(c >= curfont->numglyphs)
c = 0;
u = (c % 16)*curfont->glyphwidth / (float32)curfont->tex->raster->width;
v = (c / 16)*curfont->glyphheight / (float32)curfont->tex->raster->height;
vert->setScreenX(x);
vert->setScreenY(y);
vert->setScreenZ(rw::im2d::GetNearZ());
vert->setCameraZ(cam->nearPlane);
vert->setRecipCameraZ(recipZ);
vert->setColor(255, 255, 255, 255);
vert->setU(u, recipZ);
vert->setV(v, recipZ);
vert++;
vert->setScreenX(x+curfont->glyphwidth);
vert->setScreenY(y);
vert->setScreenZ(rw::im2d::GetNearZ());
vert->setCameraZ(cam->nearPlane);
vert->setRecipCameraZ(recipZ);
vert->setColor(255, 255, 255, 255);
vert->setU(u+du, recipZ);
vert->setV(v, recipZ);
vert++;
vert->setScreenX(x);
vert->setScreenY(y+curfont->glyphheight);
vert->setScreenZ(rw::im2d::GetNearZ());
vert->setCameraZ(cam->nearPlane);
vert->setRecipCameraZ(recipZ);
vert->setColor(255, 255, 255, 255);
vert->setU(u, recipZ);
vert->setV(v+dv, recipZ);
vert++;
vert->setScreenX(x+curfont->glyphwidth);
vert->setScreenY(y+curfont->glyphheight);
vert->setScreenZ(rw::im2d::GetNearZ());
vert->setCameraZ(cam->nearPlane);
vert->setRecipCameraZ(recipZ);
vert->setColor(255, 255, 255, 255);
vert->setU(u+du, recipZ);
vert->setV(v+dv, recipZ);
vert++;
*ix++ = curVert;
*ix++ = curVert+1;
*ix++ = curVert+2;
*ix++ = curVert+2;
*ix++ = curVert+1;
*ix++ = curVert+3;
curVert += 4;
curIndex += 6;
x += curfont->glyphwidth+1;
s++;
}
rw::SetRenderStatePtr(rw::TEXTURERASTER, curfont->tex->raster);
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST,
vertices, curVert, indices, curIndex);
}
void
initFont(void)
{
vga.tex = Texture::read("files/Bm437_IBM_VGA8", "");
bios.tex = Texture::read("files/Bm437_IBM_BIOS", "");
/*
FILE *foo = fopen("font.c", "w");
assert(foo);
int x, y;
rw::Image *img = rw::readTGA("vga_font.tga");
assert(img);
for(y = 0; y < img->height; y++){
for(x = 0; x < img->width; x++)
fprintf(foo, "%d, ", !!img->pixels[y*img->width + x]);
fprintf(foo, "\n");
}
*/
}
/*
#define NUMGLYPHS 256
#define GLYPHWIDTH 8
#define GLYPHHEIGHT 16
void
convertFont(void)
{
FILE *f;
Image *img;
uint8 data[NUMGLYPHS*GLYPHHEIGHT];
int32 i, x, y;
uint8 *px, *line, *glyph;
// f = fopen("font0.bin", "rb");
f = fopen("files/Bm437_IBM_VGA8.FON", "rb");
// f = fopen("files/Bm437_IBM_BIOS.FON", "rb");
if(f == nil)
return;
fseek(f, 0x65A, 0);
fread(data, 1, NUMGLYPHS*GLYPHHEIGHT, f);
fclose(f);
img = Image::create(16*GLYPHWIDTH, NUMGLYPHS/16*GLYPHHEIGHT, 32);
img->allocate();
for(i = 0; i < NUMGLYPHS; i++){
glyph = &data[i*GLYPHHEIGHT];
x = (i % 16)*GLYPHWIDTH;
y = (i / 16)*GLYPHHEIGHT;
line = &img->pixels[x*4 + y*img->stride];
for(y = 0; y < GLYPHHEIGHT; y++){
px = line;
for(x = 0; x < 8; x++){
if(*glyph & 1<<(8-x)){
*px++ = 255;
*px++ = 255;
*px++ = 255;
*px++ = 255;
}else{
*px++ = 0;
*px++ = 0;
*px++ = 0;
*px++ = 0;
}
}
glyph++;
line += img->stride;
}
}
// writeTGA(img, "files/Bm437_IBM_BIOS.tga");
writeTGA(img, "files/Bm437_IBM_VGA8.tga");
}
*/

641
vendor/librw/tools/playground/main.cpp vendored Normal file
View file

@ -0,0 +1,641 @@
#include <rw.h>
#include <skeleton.h>
#include "camera.h"
#include <assert.h>
rw::V3d zero = { 0.0f, 0.0f, 0.0f };
Camera *camera;
struct SceneGlobals {
rw::World *world;
rw::Camera *camera;
rw::Clump *clump;
} Scene;
rw::Texture *tex, *tex2;
rw::Raster *testras;
rw::EngineOpenParams engineOpenParams;
rw::Texture *frontbuffer;
bool dosoftras = 0;
namespace gen {
void tlTest(rw::Clump *clump);
}
void genIm3DTransform(void *vertices, rw::int32 numVertices, rw::Matrix *xform);
void genIm3DRenderIndexed(rw::PrimitiveType prim, void *indices, rw::int32 numIndices);
void genIm3DEnd(void);
void initFont(void);
void printScreen(const char *s, float x, float y);
void initsplines(void);
void rendersplines(void);
rw::Charset *testfont;
//#include <Windows.h>
void
Init(void)
{
// AllocConsole();
// freopen("CONIN$", "r", stdin);
// freopen("CONOUT$", "w", stdout);
// freopen("CONOUT$", "w", stderr);
sk::globals.windowtitle = "Clump viewer";
sk::globals.width = 640;
sk::globals.height = 448;
sk::globals.quit = 0;
}
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
dumpUserData(rw::UserDataArray *ar)
{
int i;
printf("name: %s\n", ar->name);
for(i = 0; i < ar->numElements; i++){
switch(ar->datatype){
case rw::USERDATAINT:
printf(" %d\n", ar->getInt(i));
break;
case rw::USERDATAFLOAT:
printf(" %f\n", ar->getFloat(i));
break;
case rw::USERDATASTRING:
printf(" %s\n", ar->getString(i));
break;
}
}
}
static rw::Frame*
dumpFrameUserDataCB(rw::Frame *f, void*)
{
using namespace rw;
int32 i;
UserDataArray *ar;
int32 n = UserDataArray::frameGetCount(f);
for(i = 0; i < n; i++){
ar = UserDataArray::frameGet(f, i);
dumpUserData(ar);
}
f->forAllChildren(dumpFrameUserDataCB, nil);
return f;
}
void
dumpUserData(rw::Clump *clump)
{
printf("Frames\n");
dumpFrameUserDataCB(clump->getFrame(), nil);
}
static rw::Frame*
getHierCB(rw::Frame *f, void *data)
{
using namespace rw;
HAnimData *hd = rw::HAnimData::get(f);
if(hd->hierarchy){
*(HAnimHierarchy**)data = hd->hierarchy;
return nil;
}
f->forAllChildren(getHierCB, data);
return f;
}
rw::HAnimHierarchy*
getHAnimHierarchyFromClump(rw::Clump *clump)
{
using namespace rw;
HAnimHierarchy *hier = nil;
getHierCB(clump->getFrame(), &hier);
return hier;
}
void
setupAtomic(rw::Atomic *atomic)
{
using namespace rw;
// just remove pipelines that we can't handle for now
// if(atomic->pipeline && atomic->pipeline->platform != rw::platform)
atomic->pipeline = NULL;
// Attach hierarchy to atomic if we're skinned
HAnimHierarchy *hier = getHAnimHierarchyFromClump(atomic->clump);
if(hier)
Skin::setHierarchy(atomic, hier);
}
static void
initHierFromFrames(rw::HAnimHierarchy *hier)
{
using namespace rw;
int32 i;
for(i = 0; i < hier->numNodes; i++){
if(hier->nodeInfo[i].frame){
hier->matrices[hier->nodeInfo[i].index] = *hier->nodeInfo[i].frame->getLTM();
}else
assert(0);
}
}
void
setupClump(rw::Clump *clump)
{
using namespace rw;
HAnimHierarchy *hier = getHAnimHierarchyFromClump(clump);
if(hier){
hier->attach();
initHierFromFrames(hier);
}
FORLIST(lnk, clump->atomics){
rw::Atomic *a = rw::Atomic::fromClump(lnk);
setupAtomic(a);
}
}
#define MUL(x, y) ((x)*(y)/255)
int
calcVCfx(int fb, int col, int a, int iter)
{
int prev = fb;
int col2 = col*2;
if(col2 > 255) col2 = 255;
for(int i = 0; i < iter; i++){
int tmp = MUL(fb, 255-a) + MUL(MUL(prev, col2), a);
tmp += MUL(prev, col);
tmp += MUL(prev, col);
prev = tmp > 255 ? 255 : tmp;
}
return prev;
}
int
calcIIIfx(int fb, int col, int a, int iter)
{
int prev = fb;
for(int i = 0; i < iter; i++){
int tmp = MUL(fb, 255-a) + MUL(MUL(prev, col), a);
prev = tmp > 255 ? 255 : tmp;
}
return prev;
}
void
postfxtest(void)
{
rw::Image *img = rw::Image::create(256, 256, 32);
img->allocate();
int x, y;
int iter;
static char filename[100];
for(iter = 0; iter < 10; iter++){
for(y = 0; y < 256; y++)
for(x = 0; x < 256; x++){
int res = calcVCfx(y, x, 30, iter);
// int res = calcIIIfx(y, x, 30, iter);
if(0 && res == y){
img->pixels[y*img->stride + x*img->bpp + 0] = 255;
img->pixels[y*img->stride + x*img->bpp + 1] = 0;
img->pixels[y*img->stride + x*img->bpp + 2] = 0;
}else{
img->pixels[y*img->stride + x*img->bpp + 0] = res;
img->pixels[y*img->stride + x*img->bpp + 1] = res;
img->pixels[y*img->stride + x*img->bpp + 2] = res;
}
img->pixels[y*img->stride + x*img->bpp + 3] = 255;
}
sprintf(filename, "vcfx_%02d.bmp", iter);
// sprintf(filename, "iiifx_%02d.bmp", iter);
rw::writeBMP(img, filename);
}
exit(0);
}
bool
InitRW(void)
{
// rw::platform = rw::PLATFORM_D3D8;
if(!sk::InitRW())
return false;
rw::d3d::isP8supported = false;
// postfxtest();
initFont();
rw::RGBA foreground = { 255, 255, 0, 255 };
rw::RGBA background = { 0, 0, 0, 0 };
rw::Charset::open();
testfont = rw::Charset::create(&foreground, &background);
assert(testfont);
foreground.blue = 255.0f;
testfont->setColors(&foreground, &background);
tex = rw::Texture::read("files/maze", nil);
tex2 = rw::Texture::read("files/checkers", nil);
const char *filename = "files/teapot.dff";
if(sk::args.argc > 1)
filename = sk::args.argv[1];
rw::StreamFile in;
if(in.open(filename, "rb") == NULL){
printf("couldn't open file\n");
return false;
}
rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL);
Scene.clump = rw::Clump::streamRead(&in);
assert(Scene.clump);
in.close();
// TEST - Set texture to the all materials of the clump
// FORLIST(lnk, Scene.clump->atomics){
// rw::Atomic *a = rw::Atomic::fromClump(lnk);
// for(int i = 0; i < a->geometry->matList.numMaterials; i++)
// a->geometry->matList.materials[i]->setTexture(tex);
// }
Scene.clump->getFrame()->translate(&zero, rw::COMBINEREPLACE);
dumpUserData(Scene.clump);
setupClump(Scene.clump);
Scene.world = rw::World::create();
rw::Light *ambient = rw::Light::create(rw::Light::AMBIENT);
ambient->setColor(0.3f, 0.3f, 0.3f);
Scene.world->addLight(ambient);
rw::V3d xaxis = { 1.0f, 0.0f, 0.0f };
rw::Light *direct = rw::Light::create(rw::Light::DIRECTIONAL);
direct->setColor(0.8f, 0.8f, 0.8f);
direct->setFrame(rw::Frame::create());
direct->getFrame()->rotate(&xaxis, 180.0f, rw::COMBINEREPLACE);
Scene.world->addLight(direct);
camera = new Camera;
Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
camera->m_rwcam = Scene.camera;
camera->m_aspectRatio = 640.0f/448.0f;
// camera->m_near = 0.5f;
camera->m_near = 1.5f;
// camera->m_far = 450.0f;
camera->m_far = 15.0f;
camera->m_target.set(0.0f, 0.0f, 0.0f);
camera->m_position.set(0.0f, -10.0f, 0.0f);
// camera->setPosition(Vec3(0.0f, 5.0f, 0.0f));
// camera->setPosition(Vec3(0.0f, -70.0f, 0.0f));
// camera->setPosition(Vec3(0.0f, -1.0f, 3.0f));
camera->update();
Scene.world->addCamera(camera->m_rwcam);
initsplines();
return true;
}
void
im2dtest(void)
{
using namespace rw::RWDEVICE;
int i;
static struct
{
float x, y;
rw::uint8 r, g, b, a;
float u, v;
} vs[4] = {
{ 0.0f, 0.0f, 255, 0, 0, 128, 0.0f, 0.0f },
{ 640.0f, 0.0f, 0, 255, 0, 128, 1.0f, 0.0f },
{ 0.0f, 448.0f, 0, 0, 255, 128, 0.0f, 1.0f },
{ 640.0f, 448.0f, 0, 255, 255, 128, 1.0f, 1.0f },
/*
{ 0.0f, 0.0f, 255, 0, 0, 128, 0.0f, 1.0f },
{ 640.0f, 0.0f, 0, 255, 0, 128, 0.0f, 0.0f },
{ 0.0f, 448.0f, 0, 0, 255, 128, 1.0f, 1.0f },
{ 640.0f, 448.0f, 0, 255, 255, 128, 1.0f, 0.0f },
*/
};
Im2DVertex verts[4];
static short indices[] = {
0, 1, 2, 3
};
float recipZ = 1.0f/Scene.camera->nearPlane;
for(i = 0; i < 4; i++){
verts[i].setScreenX(vs[i].x);
verts[i].setScreenY(vs[i].y);
verts[i].setScreenZ(rw::im2d::GetNearZ());
verts[i].setCameraZ(Scene.camera->nearPlane);
verts[i].setRecipCameraZ(recipZ);
verts[i].setColor(vs[i].r, vs[i].g, vs[i].b, vs[i].a);
if(dosoftras)
verts[i].setColor(255, 255, 255, 255);
verts[i].setU(vs[i].u + 0.5f/640.0f, recipZ);
verts[i].setV(vs[i].v + 0.5f/448.0f, recipZ);
}
rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
if(dosoftras)
rw::SetRenderStatePtr(rw::TEXTURERASTER, testras);
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
rw::SetRenderState(rw::VERTEXALPHA, 1);
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRISTRIP,
&verts, 4, &indices, 4);
}
void
im2dtest2(void)
{
using namespace rw::RWDEVICE;
int i;
rw::Camera *cam = Scene.camera;
float n = cam->nearPlane;
float f = cam->farPlane;
float mid = (n+f)/4.0f;
struct
{
float x, y, z;
rw::uint8 r, g, b, a;
float u, v;
} vs[4] = {
{ 0.5f, 0.5f, n, 255, 255, 255, 255, 0.0f, 0.0f },
{ 0.5f, 0.5f, mid, 255, 255, 255, 255, 1.0f, 0.0f },
{ 0.5f, -0.5f, n, 255, 255, 255, 255, 0.0f, 1.0f },
{ 0.5f, -0.5f, mid, 255, 255, 255, 255, 1.0f, 1.0f },
};
Im2DVertex verts[4];
static short indices[] = {
0, 1, 2, 3
};
for(i = 0; i < 4; i++){
float recipZ = 1.0f/vs[i].z;
verts[i].setScreenX((vs[i].x*recipZ + 0.5f) * 640.0f);
verts[i].setScreenY((vs[i].y*recipZ + 0.5f) * 448.0f);
verts[i].setScreenZ(recipZ * cam->zScale + cam->zShift);
// verts[i].setCameraZ(vs[i].z);
verts[i].setRecipCameraZ(recipZ);
verts[i].setColor(vs[i].r, vs[i].g, vs[i].b, vs[i].a);
if(dosoftras)
verts[i].setColor(255, 255, 255, 255);
verts[i].setU(vs[i].u + 0.5f/640.0f, recipZ);
verts[i].setV(vs[i].v + 0.5f/448.0f, recipZ);
}
rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
rw::SetRenderState(rw::VERTEXALPHA, 1);
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRISTRIP,
&verts, 4, &indices, 4);
}
void
im3dtest(void)
{
using namespace rw::RWDEVICE;
int i;
static struct
{
float x, y, z;
rw::uint8 r, g, b, a;
float u, v;
} vs[8] = {
{ -1.0f, -1.0f, -1.0f, 255, 0, 0, 128, 0.0f, 0.0f },
{ -1.0f, 1.0f, -1.0f, 0, 255, 0, 128, 0.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f, 0, 0, 255, 128, 1.0f, 0.0f },
{ 1.0f, 1.0f, -1.0f, 255, 0, 255, 128, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f, 255, 0, 0, 128, 0.0f, 0.0f },
{ -1.0f, 1.0f, 1.0f, 0, 255, 0, 128, 0.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 0, 0, 255, 128, 1.0f, 0.0f },
{ 1.0f, 1.0f, 1.0f, 255, 0, 255, 128, 1.0f, 1.0f },
};
Im3DVertex verts[8];
static short indices[2*6] = {
0, 1, 2, 2, 1, 3,
4, 5, 6, 6, 5, 7
};
for(i = 0; i < 8; i++){
verts[i].setX(vs[i].x);
verts[i].setY(vs[i].y);
verts[i].setZ(vs[i].z);
verts[i].setColor(vs[i].r, vs[i].g, vs[i].b, vs[i].a);
verts[i].setU(vs[i].u);
verts[i].setV(vs[i].v);
}
rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
// rw::SetRenderStatePtr(rw::TEXTURERASTER, testfont->raster);
// rw::SetRenderStatePtr(rw::TEXTURERASTER, frontbuffer->raster);
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
/*
genIm3DTransform(verts, 8, nil);
genIm3DRenderIndexed(rw::PRIMTYPETRILIST, indices, 12);
genIm3DEnd();
*/
rw::im3d::Transform(verts, 8, nil, rw::im3d::EVERYTHING);
rw::im3d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, indices, 12);
rw::im3d::End();
}
void
getFrontBuffer(void)
{
rw::Raster *fb = Scene.camera->frameBuffer;
if(frontbuffer == nil || fb->width > frontbuffer->raster->width || fb->height > frontbuffer->raster->height){
int w, h;
for(w = 1; w < fb->width; w <<= 1);
for(h = 1; h < fb->height; h <<= 1);
rw::Raster *ras = rw::Raster::create(w, h, fb->depth, rw::Raster::CAMERATEXTURE);
if(frontbuffer){
frontbuffer->raster->destroy();
frontbuffer->raster = ras;
}else
frontbuffer = rw::Texture::create(ras);
printf("created FB with %d %d %d\n", ras->width, ras->height, ras->depth);
}
rw::Raster::pushContext(frontbuffer->raster);
fb->renderFast(0, 0);
rw::Raster::popContext();
}
void
Draw(float timeDelta)
{
getFrontBuffer();
rw::SetRenderState(rw::FOGCOLOR, 0xFF0000FF);
rw::SetRenderState(rw::FOGENABLE, 1);
camera->m_rwcam->fogPlane = camera->m_rwcam->nearPlane;
static rw::RGBA clearcol = { 161, 161, 161, 0xFF };
camera->m_rwcam->clear(&clearcol, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
camera->update();
camera->m_rwcam->beginUpdate();
extern void beginSoftras(void);
beginSoftras();
// gen::tlTest(Scene.clump);
void drawtest(void);
// drawtest();
extern void endSoftras(void);
if(dosoftras){
endSoftras();
}
//im2dtest();
im2dtest2();
// Scene.clump->render();
// im3dtest();
// printScreen("Hello, World!", 10, 10);
// testfont->print("foo ABC", 200, 200, true);
// rendersplines();
camera->m_rwcam->endUpdate();
camera->m_rwcam->showRaster(0);
}
void
KeyUp(int key)
{
}
void
KeyDown(int key)
{
switch(key){
case 'W':
camera->orbit(0.0f, 0.1f);
break;
case 'S':
camera->orbit(0.0f, -0.1f);
break;
case 'A':
camera->orbit(-0.1f, 0.0f);
break;
case 'D':
camera->orbit(0.1f, 0.0f);
break;
case sk::KEY_UP:
camera->turn(0.0f, 0.1f);
break;
case sk::KEY_DOWN:
camera->turn(0.0f, -0.1f);
break;
case sk::KEY_LEFT:
camera->turn(0.1f, 0.0f);
break;
case sk::KEY_RIGHT:
camera->turn(-0.1f, 0.0f);
break;
case 'R':
camera->zoom(0.1f);
break;
case 'F':
camera->zoom(-0.1f);
break;
case 'V':
dosoftras = !dosoftras;
break;
case sk::KEY_ESC:
sk::globals.quit = 1;
break;
}
}
void
MouseMove(int x, int y)
{
}
void
MouseButton(int buttons)
{
}
sk::EventStatus
AppEventHandler(sk::Event e, void *param)
{
using namespace sk;
Rect *r;
MouseState *ms;
switch(e){
case INITIALIZE:
Init();
return EVENTPROCESSED;
case RWINITIALIZE:
return ::InitRW() ? EVENTPROCESSED : EVENTERROR;
case PLUGINATTACH:
return attachPlugins() ? EVENTPROCESSED : EVENTERROR;
case KEYDOWN:
KeyDown(*(int*)param);
return EVENTPROCESSED;
case KEYUP:
KeyUp(*(int*)param);
return EVENTPROCESSED;
case MOUSEBTN:
ms = (MouseState*)param;
MouseButton(ms->buttons);
return EVENTPROCESSED;
case MOUSEMOVE:
ms = (MouseState*)param;
MouseMove(ms->posx, ms->posy);
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;
if(camera)
camera->m_aspectRatio = (float)r->w/r->h;
if(Scene.camera)
sk::CameraSize(Scene.camera, r);
break;
case IDLE:
Draw(*(float*)param);
return EVENTPROCESSED;
}
return sk::EVENTNOTPROCESSED;
}

View file

@ -0,0 +1,902 @@
#include <rw.h>
#include <skeleton.h>
namespace rs {
typedef int8_t i8;
typedef uint8_t u8;
typedef int16_t i16;
typedef uint16_t u16;
typedef int32_t i32;
typedef uint32_t u32;
typedef int64_t i64;
typedef uint64_t u64;
typedef struct Canvas Canvas;
struct Canvas
{
u8 *fb;
u32 *zbuf;
int w, h;
};
extern Canvas *canvas;
typedef struct Texture Texture;
struct Texture
{
u8 *pixels;
int w, h;
int wrap;
};
typedef struct Point3 Point3;
struct Point3
{
int x, y, z;
};
typedef struct Color Color;
struct Color
{
u8 r, g, b, a;
};
typedef struct Vertex Vertex;
struct Vertex
{
i32 x, y, z;
float q; // 1/z
u8 r, g, b, a;
u8 f; // fog
float s, t;
};
Canvas *makecanvas(int w, int h);
Texture *maketexture(int w, int h);
void putpixel(Canvas *canvas, Point3 p, Color c);
void clearcanvas(Canvas *canvas);
void drawTriangle(Canvas *canvas, Vertex p1, Vertex p2, Vertex p3);
// not good
void drawRect(Canvas *canvas, Point3 p1, Point3 p2, Color c);
void drawLine(Canvas *canvas, Point3 p1, Point3 p2, Color c);
//#define trace(...) printf(__VA_ARGS__)
#define trace(...)
int clamp(int x);
/*
* Render States
*/
enum TextureWrap {
WRAP_REPEAT,
WRAP_CLAMP,
WRAP_BORDER,
};
enum TextureFunction {
TFUNC_MODULATE,
TFUNC_DECAL,
TFUNC_HIGHLIGHT,
TFUNC_HIGHLIGHT2,
};
enum AlphaTestFunc {
ALPHATEST_NEVER,
ALPHATEST_ALWAYS,
ALPHATEST_LESS,
ALPHATEST_LEQUAL,
ALPHATEST_EQUAL,
ALPHATEST_GEQUAL,
ALPHATEST_GREATER,
ALPHATEST_NOTEQUAL,
};
enum AlphaTestFail {
ALPHAFAIL_KEEP,
ALPHAFAIL_FB_ONLY,
ALPHAFAIL_ZB_ONLY,
};
enum DepthTestFunc {
DEPTHTEST_NEVER,
DEPTHTEST_ALWAYS,
DEPTHTEST_GEQUAL,
DEPTHTEST_GREATER,
};
// The blend equation is
// out = ((A - B) * C >> 7) + D
// A, B and D select the color, C the alpha value
enum AlphaBlendOp {
ALPHABLEND_SRC,
ALPHABLEND_DST,
ALPHABLEND_ZERO,
ALPHABLEND_FIX = ALPHABLEND_ZERO,
};
extern int srScissorX0, srScissorX1;
extern int srScissorY0, srScissorY1;
extern int srDepthTestEnable;
extern int srDepthTestFunction;
extern int srWriteZ;
extern int srAlphaTestEnable;
extern int srAlphaTestFunction;
extern int srAlphaTestReference;
extern int srAlphaTestFail;
extern int srAlphaBlendEnable;
extern int srAlphaBlendA;
extern int srAlphaBlendB;
extern int srAlphaBlendC;
extern int srAlphaBlendD;
extern int srAlphaBlendFix;
extern int srTexEnable;
extern Texture *srTexture;
extern int srWrapU;
extern int srWrapV;
extern Color srBorder;
extern int srTexUseAlpha;
extern int srTexFunc;
extern int srFogEnable;
extern Color srFogCol;
// end header
#define CEIL(p) (((p)+15) >> 4)
// render states
int srScissorX0, srScissorX1;
int srScissorY0, srScissorY1;
int srDepthTestEnable = 1;
int srDepthTestFunction = DEPTHTEST_GEQUAL;
int srWriteZ = 1;
int srAlphaTestEnable = 1;
int srAlphaTestFunction = ALPHATEST_ALWAYS;
int srAlphaTestReference;
int srAlphaTestFail = ALPHAFAIL_FB_ONLY;
int srAlphaBlendEnable = 1;
int srAlphaBlendA = ALPHABLEND_SRC;
int srAlphaBlendB = ALPHABLEND_DST;
int srAlphaBlendC = ALPHABLEND_SRC;
int srAlphaBlendD = ALPHABLEND_DST;
int srAlphaBlendFix = 0x80;
int srTexEnable = 0;
Texture *srTexture;
int srWrapU = WRAP_REPEAT;
int srWrapV = WRAP_REPEAT;
Color srBorder = { 255, 0, 0, 255 };
int srTexUseAlpha = 1;
int srTexFunc = TFUNC_MODULATE;
int srFogEnable = 0;
Color srFogCol = { 0, 0, 0, 0 };
int clamp(int x) { if(x < 0) return 0; if(x > 255) return 255; return x; }
Canvas*
makecanvas(int w, int h)
{
Canvas *canv;
canv = (Canvas*)malloc(sizeof(*canv) + w*h*(4+4));
canv->w = w;
canv->h = h;
canv->fb = ((u8*)canv + sizeof(*canv));
canv->zbuf = (u32*)(canv->fb + w*h*4);
return canv;
}
Texture*
maketexture(int w, int h)
{
Texture *t;
t = (Texture*)malloc(sizeof(*t) + w*h*4);
t->w = w;
t->h = h;
t->pixels = (u8*)t + sizeof(*t);
t->wrap = 0x11; // wrap u and v
return t;
}
void
clearcanvas(Canvas *canvas)
{
memset(canvas->fb, 0, canvas->w*canvas->h*4);
memset(canvas->zbuf, 0, canvas->w*canvas->h*4);
}
void
writefb(Canvas *canvas, int x, int y, Color c)
{
u8 *px = &canvas->fb[(y*canvas->w + x)*4];
u32 *z = &canvas->zbuf[y*canvas->w + x];
px[3] = c.r;
px[2] = c.g;
px[1] = c.b;
px[0] = c.a;
}
void
putpixel(Canvas *canvas, Point3 p, Color c)
{
// scissor test
if(p.x < srScissorX0 || p.x > srScissorX1 ||
p.y < srScissorY0 || p.y > srScissorY1)
return;
u8 *px = &canvas->fb[(p.y*canvas->w + p.x)*4];
u32 *z = &canvas->zbuf[p.y*canvas->w + p.x];
int fbwrite = 1;
int zbwrite = srWriteZ;
// alpha test
if(srAlphaTestEnable){
int fail;
switch(srAlphaTestFunction){
case ALPHATEST_NEVER:
fail = 1;
break;
case ALPHATEST_ALWAYS:
fail = 0;
break;
case ALPHATEST_LESS:
fail = c.a >= srAlphaTestReference;
break;
case ALPHATEST_LEQUAL:
fail = c.a > srAlphaTestReference;
break;
case ALPHATEST_EQUAL:
fail = c.a != srAlphaTestReference;
break;
case ALPHATEST_GEQUAL:
fail = c.a < srAlphaTestReference;
break;
case ALPHATEST_GREATER:
fail = c.a <= srAlphaTestReference;
break;
case ALPHATEST_NOTEQUAL:
fail = c.a == srAlphaTestReference;
break;
}
if(fail){
switch(srAlphaTestFail){
case ALPHAFAIL_KEEP:
return;
case ALPHAFAIL_FB_ONLY:
zbwrite = 0;
break;
case ALPHAFAIL_ZB_ONLY:
fbwrite = 0;
}
}
}
// ztest
if(srDepthTestEnable){
switch(srDepthTestFunction){
case DEPTHTEST_NEVER:
return;
case DEPTHTEST_ALWAYS:
break;
case DEPTHTEST_GEQUAL:
if((u32)p.z < *z)
return;
break;
case DEPTHTEST_GREATER:
if((u32)p.z <= *z)
return;
break;
}
}
Color d = { px[3], px[2], px[1], px[0] };
// blend
if(srAlphaBlendEnable){
int ar, ag, ab;
int br, bg, bb;
int dr, dg, db;
int ca;
switch(srAlphaBlendA){
case ALPHABLEND_SRC:
ar = c.r;
ag = c.g;
ab = c.b;
break;
case ALPHABLEND_DST:
ar = d.r;
ag = d.g;
ab = d.b;
break;
case ALPHABLEND_ZERO:
ar = 0;
ag = 0;
ab = 0;
break;
default: assert(0);
}
switch(srAlphaBlendB){
case ALPHABLEND_SRC:
br = c.r;
bg = c.g;
bb = c.b;
break;
case ALPHABLEND_DST:
br = d.r;
bg = d.g;
bb = d.b;
break;
case ALPHABLEND_ZERO:
br = 0;
bg = 0;
bb = 0;
break;
default: assert(0);
}
switch(srAlphaBlendC){
case ALPHABLEND_SRC:
ca = c.a;
break;
case ALPHABLEND_DST:
ca = d.a;
break;
case ALPHABLEND_FIX:
ca = srAlphaBlendFix;
break;
default: assert(0);
}
switch(srAlphaBlendD){
case ALPHABLEND_SRC:
dr = c.r;
dg = c.g;
db = c.b;
break;
case ALPHABLEND_DST:
dr = d.r;
dg = d.g;
db = d.b;
break;
case ALPHABLEND_ZERO:
dr = 0;
dg = 0;
db = 0;
break;
default: assert(0);
}
int r, g, b;
r = ((ar - br) * ca >> 7) + dr;
g = ((ag - bg) * ca >> 7) + dg;
b = ((ab - bb) * ca >> 7) + db;
c.r = clamp(r);
c.g = clamp(g);
c.b = clamp(b);
}
if(fbwrite)
writefb(canvas, p.x, p.y, c);
if(zbwrite)
*z = p.z;
}
Color
sampletex_nearest(int u, int v)
{
Texture *tex = srTexture;
const int usize = tex->w;
const int vsize = tex->h;
int iu = u >> 4;
int iv = v >> 4;
switch(srWrapU){
case WRAP_REPEAT:
iu %= usize;
break;
case WRAP_CLAMP:
if(iu < 0) iu = 0;
if(iu >= usize) iu = usize-1;
break;
case WRAP_BORDER:
if(iu < 0 || iu >= usize)
return srBorder;
}
switch(srWrapV){
case WRAP_REPEAT:
iv %= vsize;
break;
case WRAP_CLAMP:
if(iv < 0) iv = 0;
if(iv >= vsize) iv = vsize-1;
break;
case WRAP_BORDER:
if(iv < 0 || iv >= vsize)
return srBorder;
}
u8 *cp = &tex->pixels[(iv*tex->w + iu)*4];
Color c = { cp[0], cp[1], cp[2], cp[3] };
return c;
}
// t is texture, f is fragment
Color
texfunc(Color t, Color f)
{
int r, g, b, a;
switch(srTexFunc){
case TFUNC_MODULATE:
r = t.r * f.r >> 7;
g = t.g * f.g >> 7;
b = t.b * f.b >> 7;
a = srTexUseAlpha ?
t.a * f.a >> 7 :
f.a;
break;
case TFUNC_DECAL:
r = t.r;
g = t.g;
b = t.b;
a = srTexUseAlpha ? t.a : f.a;
break;
case TFUNC_HIGHLIGHT:
r = (t.r * f.r >> 7) + f.a;
g = (t.g * f.g >> 7) + f.a;
b = (t.b * f.b >> 7) + f.a;
a = srTexUseAlpha ?
t.a + f.a :
f.a;
break;
case TFUNC_HIGHLIGHT2:
r = (t.r * f.r >> 7) + f.a;
g = (t.g * f.g >> 7) + f.a;
b = (t.b * f.b >> 7) + f.a;
a = srTexUseAlpha ? t.a : f.a;
break;
}
Color v;
v.r = clamp(r);
v.g = clamp(g);
v.b = clamp(b);
v.a = clamp(a);
return v;
}
Point3 mkpnt(int x, int y, int z) { Point3 p = { x, y, z}; return p; }
void
drawRect(Canvas *canvas, Point3 p1, Point3 p2, Color c)
{
int x, y;
for(y = p1.y; y <= p2.y; y++)
for(x = p1.x; x <= p2.x; x++)
putpixel(canvas, mkpnt(x, y, 0), c);
}
void
drawLine(Canvas *canvas, Point3 p1, Point3 p2, Color c)
{
int dx, dy;
int incx, incy;
int e;
int x, y;
dx = abs(p2.x-p1.x);
incx = p2.x > p1.x ? 1 : -1;
dy = abs(p2.y-p1.y);
incy = p2.y > p1.y ? 1 : -1;
e = 0;
if(dx == 0){
for(y = p1.y; y != p2.y; y += incy)
putpixel(canvas, mkpnt(p1.x, y, 0), c);
}else if(dx > dy){
y = p1.y;
for(x = p1.x; x != p2.x; x += incx){
putpixel(canvas, mkpnt(x, y, 0), c);
e += dy;
if(2*e >= dx){
e -= dx;
y += incy;
}
}
}else{
x = p1.x;
for(y = p1.y; y != p2.y; y += incy){
putpixel(canvas, mkpnt(x, y, 0), c);
e += dx;
if(2*e >= dy){
e -= dy;
x += incx;
}
}
}
}
/*
attibutes we want to interpolate:
R G B A
U V / S T Q
X Y Z F
*/
struct TriAttribs
{
i64 z;
i32 r, g, b, a;
i32 f;
float s, t;
float q;
};
static void
add1(struct TriAttribs *a, struct TriAttribs *b)
{
a->z += b->z;
a->r += b->r;
a->g += b->g;
a->b += b->b;
a->a += b->a;
a->f += b->f;
a->s += b->s;
a->t += b->t;
a->q += b->q;
}
static void
sub1(struct TriAttribs *a, struct TriAttribs *b)
{
a->z -= b->z;
a->r -= b->r;
a->g -= b->g;
a->b -= b->b;
a->a -= b->a;
a->f -= b->f;
a->s -= b->s;
a->t -= b->t;
a->q -= b->q;
}
static void
guard(struct TriAttribs *a)
{
if(a->z < 0) a->z = 0;
else if(a->z > 0x3FFFFFFFC000LL) a->z = 0x3FFFFFFFC000LL;
if(a->r < 0) a->r = 0;
else if(a->r > 0xFF000) a->r = 0xFF000;
if(a->g < 0) a->g = 0;
else if(a->g > 0xFF000) a->g = 0xFF000;
if(a->b < 0) a->b = 0;
else if(a->b > 0xFF000) a->b = 0xFF000;
if(a->a < 0) a->a = 0;
else if(a->a > 0xFF000) a->a = 0xFF000;
if(a->f < 0) a->f = 0;
else if(a->f > 0xFF000) a->f = 0xFF000;
}
struct RasTri
{
int x, y;
int ymid, yend;
int right;
int e[2], dx[3], dy[3];
struct TriAttribs gx, gy, v, s;
};
static int
triangleSetup(struct RasTri *tri, Vertex v1, Vertex v2, Vertex v3)
{
int dx1, dx2, dx3;
int dy1, dy2, dy3;
dy1 = v3.y - v1.y; // long edge
if(dy1 == 0) return 1;
dx1 = v3.x - v1.x;
dx2 = v2.x - v1.x; // first small edge
dy2 = v2.y - v1.y;
dx3 = v3.x - v2.x; // second small edge
dy3 = v3.y - v2.y;
// this is twice the triangle area
const int area = dx2*dy1 - dx1*dy2;
if(area == 0) return 1;
// figure out if 0 or 1 is the right edge
tri->right = area < 0;
/* The gradients are to step whole pixels,
* so they are pre-multiplied by 16. */
float denom = 16.0f/area;
// gradients x
#define GX(p) ((v2.p - v1.p)*dy1 - (v3.p - v1.p)*dy2)
tri->gx.z = GX(z)*denom * 16384;
tri->gx.r = GX(r)*denom * 4096;
tri->gx.g = GX(g)*denom * 4096;
tri->gx.b = GX(b)*denom * 4096;
tri->gx.a = GX(a)*denom * 4096;
tri->gx.f = GX(f)*denom * 4096;
tri->gx.s = GX(s)*denom;
tri->gx.t = GX(t)*denom;
tri->gx.q = GX(q)*denom;
// gradients y
denom = -denom;
#define GY(p) ((v2.p - v1.p)*dx1 - (v3.p - v1.p)*dx2)
tri->gy.z = GY(z)*denom * 16384;
tri->gy.r = GY(r)*denom * 4096;
tri->gy.g = GY(g)*denom * 4096;
tri->gy.b = GY(b)*denom * 4096;
tri->gy.a = GY(a)*denom * 4096;
tri->gy.f = GY(f)*denom * 4096;
tri->gy.s = GY(s)*denom;
tri->gy.t = GY(t)*denom;
tri->gy.q = GY(q)*denom;
tri->ymid = CEIL(v2.y);
tri->yend = CEIL(v3.y);
tri->y = CEIL(v1.y);
tri->x = CEIL(v1.x);
tri->dy[0] = dy2<<4; // upper edge
tri->dy[1] = dy1<<4; // lower edge
tri->dy[2] = dy3<<4; // long edge
tri->dx[0] = dx2<<4;
tri->dx[1] = dx1<<4;
tri->dx[2] = dx3<<4;
// prestep to land on pixel center
int stepx = v1.x - (tri->x<<4);
int stepy = v1.y - (tri->y<<4);
tri->e[0] = (-stepy*tri->dx[0] + stepx*tri->dy[0]) >> 4;
tri->e[1] = (-stepy*tri->dx[1] + stepx*tri->dy[1]) >> 4;
// attributes along interpolated edge
// why is this cast needed? (mingw)
tri->v.z = (i64)v1.z*16384 - (stepy*tri->gy.z + stepx*tri->gx.z)/16;
tri->v.r = v1.r*4096 - (stepy*tri->gy.r + stepx*tri->gx.r)/16;
tri->v.g = v1.g*4096 - (stepy*tri->gy.g + stepx*tri->gx.g)/16;
tri->v.b = v1.b*4096 - (stepy*tri->gy.b + stepx*tri->gx.b)/16;
tri->v.a = v1.a*4096 - (stepy*tri->gy.a + stepx*tri->gx.a)/16;
tri->v.f = v1.f*4096 - (stepy*tri->gy.f + stepx*tri->gx.f)/16;
tri->v.s = v1.s - (stepy*tri->gy.s + stepx*tri->gx.s)/16.0f;
tri->v.t = v1.t - (stepy*tri->gy.t + stepx*tri->gx.t)/16.0f;
tri->v.q = v1.q - (stepy*tri->gy.q + stepx*tri->gx.q)/16.0f;
return 0;
}
void
drawTriangle(Canvas *canvas, Vertex v1, Vertex v2, Vertex v3)
{
Color c;
struct RasTri tri;
int stepx, stepy;
// Sort such that we have from top to bottom v1,v2,v3
if(v2.y < v1.y){ Vertex tmp = v1; v1 = v2; v2 = tmp; }
if(v3.y < v1.y){ Vertex tmp = v1; v1 = v3; v3 = tmp; }
if(v3.y < v2.y){ Vertex tmp = v2; v2 = v3; v3 = tmp; }
if(triangleSetup(&tri, v1, v2, v3))
return;
// Current scanline start and end
int xn[2] = { tri.x, tri.x };
int a = !tri.right; // left edge
int b = tri.right; // right edge
// If upper triangle has no height, only do the lower part
if(tri.dy[0] == 0)
goto secondtri;
while(tri.y < tri.yend){
/* TODO: is this the righ way to step the edges? */
/* Step x and interpolated value down left edge */
while(tri.e[a] <= -tri.dy[a]){
xn[a]--;
tri.e[a] += tri.dy[a];
sub1(&tri.v, &tri.gx);
}
while(tri.e[a] > 0){
xn[a]++;
tri.e[a] -= tri.dy[a];
add1(&tri.v, &tri.gx);
}
/* Step x down right edge */
while(tri.e[b] <= -tri.dy[b]){
xn[b]--;
tri.e[b] += tri.dy[b];
}
while(tri.e[b] > 0){
xn[b]++;
tri.e[b] -= tri.dy[b];
}
// When we reach the mid vertex, change state and jump to start of loop again
// TODO: this is a bit ugly in here...can we fix it?
if(tri.y == tri.ymid){
secondtri:
tri.dx[0] = tri.dx[2];
tri.dy[0] = tri.dy[2];
// Either the while prevents this or we returned early because dy1 == 0
assert(tri.dy[0] != 0);
stepx = v2.x - (xn[0]<<4);
stepy = v2.y - (tri.y<<4);
tri.e[0] = (-stepy*tri.dx[0] + stepx*tri.dy[0]) >> 4;
tri.ymid = -1; // so we don't do this again
continue;
}
/* Rasterize one line */
tri.s = tri.v;
for(tri.x = xn[a]; tri.x < xn[b]; tri.x++){
guard(&tri.s);
c.r = tri.s.r >> 12;
c.g = tri.s.g >> 12;
c.b = tri.s.b >> 12;
c.a = tri.s.a >> 12;
if(srTexEnable && srTexture){
float w = 1.0f/tri.s.q;
float s = tri.s.s * w;
float t = tri.s.t * w;
int u = s * srTexture->w * 16;
int v = t * srTexture->h * 16;
Color texc = sampletex_nearest(u, v);
c = texfunc(texc, c);
}
if(srFogEnable){
const int f = tri.s.f >> 12;
c.r = (f*c.r >> 8) + ((255 - f)*srFogCol.r >> 8);
c.g = (f*c.g >> 8) + ((255 - f)*srFogCol.g >> 8);
c.b = (f*c.b >> 8) + ((255 - f)*srFogCol.b >> 8);
}
putpixel(canvas, mkpnt(tri.x, tri.y, tri.s.z>>14), c);
add1(&tri.s, &tri.gx);
}
/* Step in y */
tri.y++;
tri.e[a] += tri.dx[a];
tri.e[b] += tri.dx[b];
add1(&tri.v, &tri.gy);
}
}
Canvas *canvas;
}
using namespace rw;
void
rastest_renderTriangles(RWDEVICE::Im2DVertex *scrverts, int32 numVerts, uint16 *indices, int32 numTris)
{
int i;
RGBA col;
rs::Vertex v[3];
RWDEVICE::Im2DVertex *iv;
rs::srDepthTestEnable = 1;
rs::srAlphaTestEnable = 0;
rs::srTexEnable = 0;
rs::srAlphaBlendEnable = 0;
while(numTris--){
for(i = 0; i < 3; i++){
iv = &scrverts[indices[i]];
v[i].x = iv->getScreenX() * 16.0f;
v[i].y = iv->getScreenY() * 16.0f;
v[i].z = 16777216*(1.0f-iv->getScreenZ());
v[i].q = iv->getRecipCameraZ();
col = iv->getColor();
v[i].r = col.red;
v[i].g = col.green;
v[i].b = col.blue;
v[i].a = col.alpha;
v[i].f = 0;
v[i].s = iv->u*iv->getRecipCameraZ();
v[i].t = iv->v*iv->getRecipCameraZ();
}
drawTriangle(rs::canvas, v[0], v[1], v[2]);
indices += 3;
}
}
extern rw::Raster *testras;
void
beginSoftras(void)
{
Camera *cam = (Camera*)engine->currentCamera;
if(rs::canvas == nil ||
cam->frameBuffer->width != rs::canvas->w ||
cam->frameBuffer->height != rs::canvas->h){
rs::canvas = rs::makecanvas(cam->frameBuffer->width, cam->frameBuffer->height);
testras = rw::Raster::create(rs::canvas->w, rs::canvas->h, 32, rw::Raster::C8888);
}
clearcanvas(rs::canvas);
rs::srScissorX0 = 0;
rs::srScissorX1 = rs::canvas->w-1;
rs::srScissorY0 = 0;
rs::srScissorY1 = rs::canvas->h-1;
}
void
endSoftras(void)
{
int i;
uint8 *dst = testras->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
if(dst == nil)
return;
uint8 *src = rs::canvas->fb;
for(i = 0; i < rs::canvas->w*rs::canvas->h; i++){
dst[0] = src[1];
dst[1] = src[2];
dst[2] = src[3];
dst[3] = src[0];
dst += 4;
src += 4;
}
// abgr in canvas
// bgra in raster
testras->unlock(0);
}
/*
typedef struct PixVert PixVert;
struct PixVert
{
float x, y, z, q;
int r, g, b, a;
float u, v;
};
#include "test.inc"
void
drawtest(void)
{
int i, j;
rs::Vertex v[3];
rs::srDepthTestEnable = 1;
rs::srAlphaTestEnable = 0;
rs::srTexEnable = 0;
rs::srAlphaBlendEnable = 0;
for(i = 0; i < nelem(verts); i += 3){
for(j = 0; j < 3; j++){
v[j].x = verts[i+j].x * 16.0f;
v[j].y = verts[i+j].y * 16.0f;
v[j].z = 16777216*(1.0f - verts[i+j].z);
v[j].q = verts[i+j].q;
v[j].r = verts[i+j].r;
v[j].g = verts[i+j].g;
v[j].b = verts[i+j].b;
v[j].a = verts[i+j].a;
v[j].f = 0;
v[j].s = verts[i+j].u*v[j].q;
v[j].t = verts[i+j].v*v[j].q;
}
drawTriangle(rs::canvas, v[0], v[1], v[2]);
}
//exit(0);
}
*/

View file

@ -0,0 +1,520 @@
#include <rw.h>
#include <skeleton.h>
#include <vector>
using namespace rw;
using namespace RWDEVICE;
static Im3DVertex im3dVerts[1024];
static int numImVerts;
static rw::PrimitiveType imPrim;
static Im3DVertex imVert;
void
BeginIm3D(rw::PrimitiveType prim)
{
numImVerts = 0;
imPrim = prim;
}
void
EndIm3D(void)
{
rw::im3d::Transform(im3dVerts, numImVerts, nil, rw::im3d::EVERYTHING);
rw::im3d::RenderPrimitive(imPrim);
rw::im3d::End();
}
void
AddVertex(const rw::V3d &vert)
{
if(numImVerts >= 1024){
EndIm3D();
switch(imPrim){
case PRIMTYPEPOLYLINE:
im3dVerts[0] = im3dVerts[numImVerts-1];
numImVerts = 1;
break;
case PRIMTYPETRISTRIP:
// TODO: winding?
im3dVerts[0] = im3dVerts[numImVerts-2];
im3dVerts[1] = im3dVerts[numImVerts-1];
numImVerts = 2;
break;
case PRIMTYPETRIFAN:
im3dVerts[1] = im3dVerts[numImVerts-1];
numImVerts = 2;
break;
default:
numImVerts = 0;
}
}
imVert.setX(vert.x);
imVert.setY(vert.y);
imVert.setZ(vert.z);
im3dVerts[numImVerts++] = imVert;
}
float epsilon = 0.000001;
class RBCurve
{
public:
int degree;
std::vector<V3d> verts;
std::vector<float> weights; // for rational
std::vector<float> knots;
V3d eval(float u);
void drawHull(void);
void drawSpline(void);
};
class RBSurf
{
public:
int degreeU, degreeV;
int numU, numV;
std::vector<V3d> verts;
std::vector<float> weights;
std::vector<float> knotsU, knotsV;
void update(void);
V3d eval(float u, float v);
void drawHull(void);
void drawIsoparms(void);
void drawShaded(void);
};
float div0(float a, float b) { return b == 0.0f ? a : a/b; }
// naive algorithm
float
evalBasis(int i, int d, float u, float knots[])
{
if(d == 0){
if(knots[i] <= u && u < knots[i+1])
return 1.0f;
return 0.0f;
}
float b0 = evalBasis(i, d-1, u, knots);
float b1 = evalBasis(i+1, d-1, u, knots);
return b0*div0(u-knots[i], knots[i+d] - knots[i]) + b1*div0(knots[i+d+1]-u, knots[i+d+1] - knots[i+1]);
}
float
evalBasisFast(int i, int d, float u, float knots[])
{
int r, j;
float tmp[10];
// degree 0 values
for(j = 0; j < d+1; j++)
tmp[j] = knots[i+j] <= u && u < knots[i+j+1] ? 1.0f : 0.0f;
// build up from degree zero
for(r = d, d = 1; r > 0; r--, d++){
for(j = 0; j < r; j++){
float t1 = div0(u-knots[i+j], knots[i+j + d] - knots[i+j]);
float t2 = div0(knots[i+j + d+1]-u, knots[i+j + d+1] - knots[i+j + 1]);
tmp[j] = tmp[j]*t1 + tmp[j+1]*t2;
}
}
return tmp[0];
}
V3d
RBCurve::eval(float u)
{
int i;
V3d vert = { 0.0f, 0.0f, 0.0f };
float w = 0.0f;
// Find knots we're interested in
for(i = 0; i < knots.size(); i++)
if(knots[i] <= u && u < knots[i+1])
break;
int startI = i-degree;
int endI = i+1;
for(i = startI; i < endI; i++){
float r = evalBasisFast(i, degree, u, &knots[0]);
w += weights[i]*r;
vert = add(vert, scale(verts[i], weights[i]*r));
}
return scale(vert, div0(1.0f,w));
}
void
RBCurve::drawHull(void)
{
int i;
rw::SetRenderState(rw::TEXTURERASTER, nil);
rw::SetRenderState(rw::FOGENABLE, 0);
BeginIm3D(rw::PRIMTYPEPOLYLINE);
imVert.setU(0.0f);
imVert.setV(0.0f);
imVert.setColor(138, 72, 51, 255);
// imVert.setColor(228, 172, 121, 255);
for(i = 0; i < verts.size(); i++)
AddVertex(verts[i]);
EndIm3D();
}
void
RBCurve::drawSpline(void)
{
int i;
float u, endu;
V3d vert;
rw::SetRenderState(rw::TEXTURERASTER, nil);
rw::SetRenderState(rw::FOGENABLE, 0);
BeginIm3D(rw::PRIMTYPEPOLYLINE);
imVert.setU(0.0f);
imVert.setV(0.0f);
imVert.setColor(0, 4, 96, 255);
u = knots[0];
endu = knots[knots.size()-1] - epsilon;
float uinc = (endu-knots[0])/40.0f;
for(;; u += uinc){
if(u > endu)
u = endu;
AddVertex(eval(u));
if(u >= endu)
break;
}
EndIm3D();
}
void
RBSurf::update(void)
{
numU = knotsU.size() - degreeU - 1;
numV = knotsV.size() - degreeV - 1;
}
V3d
RBSurf::eval(float u, float v)
{
int i, j;
V3d vert = { 0.0f, 0.0f, 0.0f };
float w = 0.0f;
float basisU[10], basisV[10];
// Find knots we're interested in
int k;
for(k = 0; k < knotsU.size(); k++)
if(knotsU[k] <= u && u < knotsU[k+1])
break;
int startI = k-degreeU;
int endI = k+1;
for(k = 0; k < knotsV.size(); k++)
if(knotsV[k] <= v && v < knotsV[k+1])
break;
int startJ = k-degreeV;
int endJ = k+1;
for(i = startI; i < endI; i++) basisU[i-startI] = evalBasisFast(i, degreeU, u, &knotsU[0]);
for(j = startJ; j < endJ; j++) basisV[j-startJ] = evalBasisFast(j, degreeV, v, &knotsV[0]);
for(j = startJ; j < endJ; j++)
for(i = startI; i < endI; i++){
float r = basisV[j-startJ]*basisU[i-startI];
w += weights[j*numU + i]*r;
vert = add(vert, scale(verts[j*numU + i], weights[j*numU + i]*r));
}
return scale(vert, div0(1.0f,w));
}
void
RBSurf::drawHull(void)
{
rw::SetRenderState(rw::TEXTURERASTER, nil);
rw::SetRenderState(rw::FOGENABLE, 0);
imVert.setU(0.0f);
imVert.setV(0.0f);
imVert.setColor(138, 72, 51, 255);
// imVert.setColor(228, 172, 121, 255);
int iu, iv;
for(iv = 0; iv < numV; iv++){
BeginIm3D(rw::PRIMTYPEPOLYLINE);
for(iu = 0; iu < numU; iu++)
AddVertex(verts[iu + iv*numU]);
EndIm3D();
}
for(iu = 0; iu < numU; iu++){
BeginIm3D(rw::PRIMTYPEPOLYLINE);
for(iv = 0; iv < numV; iv++)
AddVertex(verts[iu + iv*numU]);
EndIm3D();
}
}
void
RBSurf::drawIsoparms(void)
{
V3d vert;
int iu, iv;
float u, v;
rw::SetRenderState(rw::TEXTURERASTER, nil);
rw::SetRenderState(rw::FOGENABLE, 0);
imVert.setU(0.0f);
imVert.setV(0.0f);
imVert.setColor(0, 4, 96, 255);
float endu = knotsU[knotsU.size()-1] - epsilon;
float endv = knotsU[knotsV.size()-1] - epsilon;
float uinc = (endu-knotsU[0])/40.0f;
float vinc = (endv-knotsV[0])/40.0f;
v = -100000.0f;
for(iv = 0; iv < knotsV.size(); iv++){
if(knotsV[iv] <= v) continue;
v = knotsV[iv];
if(v > endv) v = endv;
BeginIm3D(rw::PRIMTYPEPOLYLINE);
for(u = knotsU[0];; u += uinc){
if(u > endu)
u = endu;
AddVertex(eval(u, v));
if(u >= endu)
break;
}
EndIm3D();
}
u = -100000.0f;
for(iu = 0; iu < knotsU.size(); iu++){
if(knotsU[iu] <= u) continue;
u = knotsU[iu];
if(u > endu) u = endu;
BeginIm3D(rw::PRIMTYPEPOLYLINE);
for(v = knotsV[0];; v += vinc){
if(v > endv)
v = endv;
AddVertex(eval(u, v));
if(v >= endv)
break;
}
EndIm3D();
}
}
void
RBSurf::drawShaded(void)
{
V3d vert;
int iu, iv;
float u, v;
rw::SetRenderState(rw::TEXTURERASTER, nil);
rw::SetRenderState(rw::FOGENABLE, 0);
imVert.setU(0.0f);
imVert.setV(0.0f);
imVert.setColor(0, 128, 240, 255);
float endu = knotsU[knotsU.size()-1] - epsilon;
float endv = knotsU[knotsV.size()-1] - epsilon;
float uinc = (endu-knotsU[0])/40.0f;
float vinc = (endv-knotsV[0])/40.0f;
float vnext;
for(v = knotsV[0];; v = vnext){
if(v > endv)
v = endv;
vnext = v + vinc;
BeginIm3D(rw::PRIMTYPETRISTRIP);
for(u = knotsU[0];; u += uinc){
if(u > endu)
u = endu;
AddVertex(eval(u, v));
AddVertex(eval(u, vnext));
if(u >= endu)
break;
}
EndIm3D();
if(vnext >= endv)
break;
}
}
RBCurve testspline1, testspline2;
RBSurf testsurf;
void
initsplines(void)
{
V3d vert;
testspline1.degree = 3;
testspline1.verts.clear();
testspline1.weights.clear();
vert.set(-30.63383, 22.65459, 0);
vert = scale(vert, 1.0f/20.0f);
testspline1.verts.push_back(vert);
testspline1.weights.push_back(1.0f);
vert.set(13.50783, 33.01786, 15.06403);
vert = scale(vert, 1.0f/20.0f);
testspline1.verts.push_back(vert);
testspline1.weights.push_back(1.0f);
vert.set(34.252, -10.36327, 15.06403);
vert = scale(vert, 1.0f/20.0f);
testspline1.verts.push_back(vert);
testspline1.weights.push_back(1.0f);
vert.set(-7.959972, -1.205032, 0);
vert = scale(vert, 1.0f/20.0f);
testspline1.verts.push_back(vert);
testspline1.weights.push_back(1.0f);
vert.set(6.995127, -41.32158, -18.19684);
vert = scale(vert, 1.0f/20.0f);
testspline1.verts.push_back(vert);
testspline1.weights.push_back(1.0f);
testspline1.knots.clear();
testspline1.knots.push_back(0);
testspline1.knots.push_back(0);
testspline1.knots.push_back(0);
testspline1.knots.push_back(0);
testspline1.knots.push_back(1);
testspline1.knots.push_back(2);
testspline1.knots.push_back(2);
testspline1.knots.push_back(2);
testspline1.knots.push_back(2);
testspline2.degree = 2;
testspline2.verts.clear();
#define V(x, y, z) \
vert.set(x, y, z); \
testspline2.verts.push_back(scale(vert, 1.0f/20.0f)); \
testspline2.weights.push_back(1.0f);
V(-61.9913, 9.158239, 0);
V(-32.32231, 27.23371, 0);
V(25.80961, -4.820126, 0);
testspline2.knots.clear();
testspline2.knots.push_back(0);
testspline2.knots.push_back(0);
testspline2.knots.push_back(0);
testspline2.knots.push_back(1);
testspline2.knots.push_back(1);
testspline2.knots.push_back(1);
/*
testspline2 = testspline1;
// testspline2.knots.clear();
// testspline2.knots.push_back(0);
// testspline2.knots.push_back(0);
// testspline2.knots.push_back(0);
// testspline2.knots.push_back(0);
// testspline2.knots.push_back(3);
// testspline2.knots.push_back(4);
// testspline2.knots.push_back(4);
// testspline2.knots.push_back(4);
// testspline2.knots.push_back(4);
testspline1.weights[2] = 5.0f;
*/
#define V(x, y, z) \
vert.set(x, y, z); \
testsurf.verts.push_back(scale(vert, 1.0f/20.0f)); \
testsurf.weights.push_back(1.0f);
testsurf.degreeU = 3;
testsurf.degreeV = 3;
testsurf.verts.clear();
testsurf.weights.clear();
V(-69.22764, -0, 12.77366);
V(-48.72468, 0, 29.16251);
V(-24.84476, 0, 39.52605);
V(22.43265, -0, 45.79238);
V(36.4229, 0, 28.9215);
V(61.02645, 0, 6.74835);
V(86.35364, -0, 20.96809);
V(-69.22764, 9.286676, 12.77366);
V(-48.72468, 9.286676, 29.16251);
V(-24.84476, 9.286676, 39.52605);
V(22.43265, 9.286676, 45.79238);
V(36.4229, 9.286676, 28.9215);
V(61.02645, 9.286676, 6.74835);
V(86.35364, 9.286676, 20.96809);
V(-68.13416, 23.51821, 6.114491);
V(-48.19925, 23.51821, 22.27994);
V(-26.91943, 23.51821, 33.20763);
V(18.69658, 23.51821, 39.0488);
V(27.88844, 23.51821, 30.80604);
V(57.49908, 23.51821, -0.6488895);
V(86.35364, 23.51821, 14.21974);
V(-67.00163, 52.46369, -0.7825046);
V(-47.65504, 52.46369, 15.15157);
V(-29.06818, 52.46369, 26.66356);
V(14.82709, 52.46369, 32.06438);
V(19.04919, 52.46369, 32.75788);
V(53.84574, 52.46369, -8.310311);
V(86.35364, 52.46369, 7.230374);
V(-67.86079, 70.07219, 4.449699);
V(-48.06789, 70.07219, 20.5593);
V(-27.43809, 70.07219, 31.62803);
V(17.76257, 70.07219, 37.36291);
V(25.75483, 70.07219, 31.27717);
V(56.61724, 70.07219, -2.498198);
V(86.35364, 70.07219, 12.53265);
testsurf.knotsU.clear();
testsurf.knotsU.push_back(0);
testsurf.knotsU.push_back(0);
testsurf.knotsU.push_back(0);
testsurf.knotsU.push_back(0);
testsurf.knotsU.push_back(0.25);
testsurf.knotsU.push_back(0.5);
testsurf.knotsU.push_back(0.75);
testsurf.knotsU.push_back(1);
testsurf.knotsU.push_back(1);
testsurf.knotsU.push_back(1);
testsurf.knotsU.push_back(1);
testsurf.knotsV.clear();
testsurf.knotsV.push_back(0);
testsurf.knotsV.push_back(0);
testsurf.knotsV.push_back(0);
testsurf.knotsV.push_back(0);
testsurf.knotsV.push_back(0.5);
testsurf.knotsV.push_back(1);
testsurf.knotsV.push_back(1);
testsurf.knotsV.push_back(1);
testsurf.knotsV.push_back(1);
testsurf.update();
}
void
rendersplines(void)
{
testspline1.drawHull();
testspline1.drawSpline();
// testspline2.drawHull();
// testspline2.drawSpline();
testsurf.drawHull();
testsurf.drawShaded();
testsurf.drawIsoparms();
}

View file

@ -0,0 +1,766 @@
#include <rw.h>
#include <skeleton.h>
extern bool dosoftras;
using namespace rw;
using namespace RWDEVICE;
void rastest_renderTriangles(RWDEVICE::Im2DVertex *scrverts, int32 verts, uint16 *indices, int32 numTris);
//
// This is a test to implement T&L in software and render with Im2D
//
namespace gen {
#define MAX_LIGHTS 8
struct Directional {
V3d at;
RGBAf color;
};
static Directional directionals[MAX_LIGHTS];
static int32 numDirectionals;
static RGBAf ambLight;
static void
enumLights(Matrix *lightmat)
{
int32 n;
World *world;
world = (World*)engine->currentWorld;
ambLight.red = 0.0;
ambLight.green = 0.0;
ambLight.blue = 0.0;
ambLight.alpha = 0.0;
numDirectionals = 0;
// only unpositioned lights right now
FORLIST(lnk, world->globalLights){
Light *l = Light::fromWorld(lnk);
if(l->getType() == Light::DIRECTIONAL){
if(numDirectionals >= MAX_LIGHTS)
continue;
n = numDirectionals++;
V3d::transformVectors(&directionals[n].at, &l->getFrame()->getLTM()->at, 1, lightmat);
directionals[n].color = l->color;
directionals[n].color.alpha = 0.0f;
}else if(l->getType() == Light::AMBIENT){
ambLight.red += l->color.red;
ambLight.green += l->color.green;
ambLight.blue += l->color.blue;
}
}
}
struct ObjSpace3DVertex
{
V3d objVertex;
V3d objNormal;
RGBA color;
TexCoords texCoords;
};
enum {
CLIPXLO = 0x01,
CLIPXHI = 0x02,
CLIPX = 0x03,
CLIPYLO = 0x04,
CLIPYHI = 0x08,
CLIPY = 0x0C,
CLIPZLO = 0x10,
CLIPZHI = 0x20,
CLIPZ = 0x30,
};
struct CamSpace3DVertex
{
V3d camVertex;
uint8 clipFlags;
RGBAf color;
TexCoords texCoords;
};
struct InstanceData
{
uint16 *indices;
int32 numIndices;
ObjSpace3DVertex *vertices;
int32 numVertices;
// int vertStride; // not really needed right now
Material *material;
Mesh *mesh;
};
struct InstanceDataHeader : public rw::InstanceDataHeader
{
uint32 serialNumber;
ObjSpace3DVertex *vertices;
uint16 *indices;
InstanceData *inst;
};
static void
instanceAtomic(Atomic *atomic)
{
static V3d zeroNorm = { 0.0f, 0.0f, 0.0f };
static RGBA black = { 0, 0, 0, 255 };
static TexCoords zeroTex = { 0.0f, 0.0f };
int i;
uint j;
int x, x1, x2, x3;
Geometry *geo;
MeshHeader *header;
Mesh *mesh;
InstanceDataHeader *insthead;
InstanceData *inst;
uint32 firstVert;
uint16 *srcindices, *dstindices;
geo = atomic->geometry;
if(geo->instData)
return;
header = geo->meshHeader;
int numTris;
if(header->flags & MeshHeader::TRISTRIP)
numTris = header->totalIndices - 2*header->numMeshes;
else
numTris = header->totalIndices / 3;
int size;
size = sizeof(InstanceDataHeader) + header->numMeshes*sizeof(InstanceData) +
geo->numVertices*sizeof(ObjSpace3DVertex) + numTris*6*sizeof(uint16);
insthead = (InstanceDataHeader*)rwNew(size, ID_GEOMETRY);
geo->instData = insthead;
insthead->platform = 0;
insthead->serialNumber = header->serialNum;
inst = (InstanceData*)(insthead+1);
insthead->inst = inst;
insthead->vertices = (ObjSpace3DVertex*)(inst+header->numMeshes);
dstindices = (uint16*)(insthead->vertices+geo->numVertices);
insthead->indices = dstindices;
// TODO: morphing
MorphTarget *mt = geo->morphTargets;
for(i = 0; i < geo->numVertices; i++){
insthead->vertices[i].objVertex = mt->vertices[i];
if(geo->flags & Geometry::NORMALS)
insthead->vertices[i].objNormal = mt->normals[i];
else
insthead->vertices[i].objNormal = zeroNorm;
if(geo->flags & Geometry::PRELIT)
insthead->vertices[i].color = geo->colors[i];
else
insthead->vertices[i].color = black;
if(geo->numTexCoordSets > 0)
insthead->vertices[i].texCoords = geo->texCoords[0][i];
else
insthead->vertices[i].texCoords = zeroTex;
}
mesh = header->getMeshes();
for(i = 0; i < header->numMeshes; i++){
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
&firstVert, &inst->numVertices);
inst->indices = dstindices;
inst->vertices = &insthead->vertices[firstVert];
inst->mesh = mesh;
inst->material = mesh->material;
srcindices = mesh->indices;
if(header->flags & MeshHeader::TRISTRIP){
inst->numIndices = 0;
x = 0;
for(j = 0; j < mesh->numIndices-2; j++){
x1 = srcindices[j+x];
x ^= 1;
x2 = srcindices[j+x];
x3 = srcindices[j+2];
if(x1 != x2 && x2 != x3 && x1 != x3){
dstindices[0] = x1;
dstindices[1] = x2;
dstindices[2] = x3;
dstindices += 3;
inst->numIndices += 3;
}
}
}else{
inst->numIndices = mesh->numIndices;
for(j = 0; j < mesh->numIndices; j += 3){
dstindices[0] = srcindices[j+0] - firstVert;
dstindices[1] = srcindices[j+1] - firstVert;
dstindices[2] = srcindices[j+2] - firstVert;
dstindices += 3;
}
}
inst++;
mesh++;
}
}
struct MeshState
{
int32 flags;
Matrix obj2cam;
Matrix obj2world;
int32 numVertices;
int32 numPrimitives;
SurfaceProperties surfProps;
RGBA matCol;
};
static void
cam2screen(Im2DVertex *scrvert, CamSpace3DVertex *camvert)
{
RGBA col;
float32 recipZ;
Camera *cam = (Camera*)engine->currentCamera;
int32 width = cam->frameBuffer->width;
int32 height = cam->frameBuffer->height;
recipZ = 1.0f/camvert->camVertex.z;
// scrvert->setScreenX(camvert->camVertex.x * recipZ * width);
// scrvert->setScreenY(camvert->camVertex.y * recipZ * height);
scrvert->setScreenX(camvert->camVertex.x * recipZ * width/2 + width/4);
scrvert->setScreenY(camvert->camVertex.y * recipZ * height/2 + height/4);
scrvert->setScreenZ(recipZ * cam->zScale + cam->zShift);
scrvert->setCameraZ(camvert->camVertex.z);
scrvert->setRecipCameraZ(recipZ);
scrvert->setU(camvert->texCoords.u, recipZ);
scrvert->setV(camvert->texCoords.v, recipZ);
convColor(&col, &camvert->color);
scrvert->setColor(col.red, col.green, col.blue, col.alpha);
}
static void
transform(MeshState *mstate, ObjSpace3DVertex *objverts, CamSpace3DVertex *camverts, Im2DVertex *scrverts)
{
int32 i;
float32 z;
Camera *cam = (Camera*)engine->currentCamera;
for(i = 0; i < mstate->numVertices; i++){
V3d::transformPoints(&camverts[i].camVertex, &objverts[i].objVertex, 1, &mstate->obj2cam);
convColor(&camverts[i].color, &objverts[i].color);
camverts[i].texCoords = objverts[i].texCoords;
camverts[i].clipFlags = 0;
z = camverts[i].camVertex.z;
// 0 < x < z
if(camverts[i].camVertex.x >= z) camverts[i].clipFlags |= CLIPXHI;
if(camverts[i].camVertex.x <= 0) camverts[i].clipFlags |= CLIPXLO;
// 0 < y < z
if(camverts[i].camVertex.y >= z) camverts[i].clipFlags |= CLIPYHI;
if(camverts[i].camVertex.y <= 0) camverts[i].clipFlags |= CLIPYLO;
// near < z < far
if(z >= cam->farPlane) camverts[i].clipFlags |= CLIPZHI;
if(z <= cam->nearPlane) camverts[i].clipFlags |= CLIPZLO;
cam2screen(&scrverts[i], &camverts[i]);
}
}
static void
light(MeshState *mstate, ObjSpace3DVertex *objverts, CamSpace3DVertex *camverts)
{
int32 i;
RGBAf colf;
RGBAf amb = ambLight;
amb = scale(ambLight, mstate->surfProps.ambient);
for(i = 0; i < mstate->numVertices; i++){
camverts[i].color = add(camverts[i].color, amb);
if((mstate->flags & Geometry::NORMALS) == 0)
continue;
for(int32 k = 0; k < numDirectionals; k++){
float32 f = dot(objverts[i].objNormal, neg(directionals[k].at));
if(f <= 0.0f) continue;
f *= mstate->surfProps.diffuse;
colf = scale(directionals[k].color, f);
camverts[i].color = add(camverts[i].color, colf);
}
}
}
static void
postlight(MeshState *mstate, CamSpace3DVertex *camverts, Im2DVertex *scrverts)
{
int32 i;
RGBA col;
RGBAf colf;
for(i = 0; i < mstate->numVertices; i++){
convColor(&colf, &mstate->matCol);
camverts[i].color = modulate(camverts[i].color, colf);
clamp(&camverts[i].color);
convColor(&col, &camverts[i].color);
scrverts[i].setColor(col.red, col.green, col.blue, col.alpha);
}
}
static int32
cullTriangles(MeshState *mstate, CamSpace3DVertex *camverts, uint16 *indices, uint16 *clipindices)
{
int32 i;
int32 x1, x2, x3;
int32 newNumPrims;
int32 numClip;
newNumPrims = 0;
numClip = 0;
for(i = 0; i < mstate->numPrimitives; i++, indices += 3){
x1 = indices[0];
x2 = indices[1];
x3 = indices[2];
// Only a simple frustum call
if(camverts[x1].clipFlags &
camverts[x2].clipFlags &
camverts[x3].clipFlags)
continue;
if(camverts[x1].clipFlags |
camverts[x2].clipFlags |
camverts[x3].clipFlags)
numClip++;
// The Triangle is in, probably
clipindices[0] = x1;
clipindices[1] = x2;
clipindices[2] = x3;
clipindices += 3;
newNumPrims++;
}
mstate->numPrimitives = newNumPrims;
return numClip;
}
static void
interpVertex(CamSpace3DVertex *out, CamSpace3DVertex *v1, CamSpace3DVertex *v2, float32 t)
{
float32 z;
float32 invt;
Camera *cam = (Camera*)engine->currentCamera;
invt = 1.0f - t;
out->camVertex = add(scale(v1->camVertex, invt), scale(v2->camVertex, t));
out->color = add(scale(v1->color, invt), scale(v2->color, t));
out->texCoords.u = v1->texCoords.u*invt + v2->texCoords.u*t;
out->texCoords.v = v1->texCoords.v*invt + v2->texCoords.v*t;
out->clipFlags = 0;
z = out->camVertex.z;
// 0 < x < z
if(out->camVertex.x >= z) out->clipFlags |= CLIPXHI;
if(out->camVertex.x <= 0) out->clipFlags |= CLIPXLO;
// 0 < y < z
if(out->camVertex.y >= z) out->clipFlags |= CLIPYHI;
if(out->camVertex.y <= 0) out->clipFlags |= CLIPYLO;
// near < z < far
if(z >= cam->farPlane) out->clipFlags |= CLIPZHI;
if(z <= cam->nearPlane) out->clipFlags |= CLIPZLO;
}
static void
clipTriangles(MeshState *mstate, CamSpace3DVertex *camverts, Im2DVertex *scrverts, uint16 *indices, uint16 *clipindices)
{
int32 i, j;
int32 x1, x2, x3;
int32 newNumPrims;
CamSpace3DVertex buf[18];
CamSpace3DVertex *in, *out, *tmp;
int32 nin, nout;
float32 t;
Camera *cam = (Camera*)engine->currentCamera;
newNumPrims = 0;
for(i = 0; i < mstate->numPrimitives; i++, indices += 3){
x1 = indices[0];
x2 = indices[1];
x3 = indices[2];
if((camverts[x1].clipFlags |
camverts[x2].clipFlags |
camverts[x3].clipFlags) == 0){
// all inside
clipindices[0] = x1;
clipindices[1] = x2;
clipindices[2] = x3;
clipindices += 3;
newNumPrims++;
continue;
}
// set up triangle
in = &buf[0];
out = &buf[9];
in[0] = camverts[x1];
in[1] = camverts[x2];
in[2] = camverts[x3];
nin = 3;
nout = 0;
#define V(a) in[a].camVertex.
// clip z near
for(j = 0; j < nin; j++){
x1 = j;
x2 = (j+1) % nin;
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPZLO){
t = (cam->nearPlane - V(x1)z)/(V(x2)z - V(x1)z);
interpVertex(&out[nout++], &in[x1], &in[x2], t);
}
if((in[x2].clipFlags & CLIPZLO) == 0)
out[nout++] = in[x2];
}
// clip z far
nin = nout; nout = 0;
tmp = in; in = out; out = tmp;
for(j = 0; j < nin; j++){
x1 = j;
x2 = (j+1) % nin;
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPZHI){
t = (cam->farPlane - V(x1)z)/(V(x2)z - V(x1)z);
interpVertex(&out[nout++], &in[x1], &in[x2], t);
}
if((in[x2].clipFlags & CLIPZHI) == 0)
out[nout++] = in[x2];
}
// clip y 0
nin = nout; nout = 0;
tmp = in; in = out; out = tmp;
for(j = 0; j < nin; j++){
x1 = j;
x2 = (j+1) % nin;
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPYLO){
t = -V(x1)y/(V(x2)y - V(x1)y);
interpVertex(&out[nout++], &in[x1], &in[x2], t);
}
if((in[x2].clipFlags & CLIPYLO) == 0)
out[nout++] = in[x2];
}
// clip y z
nin = nout; nout = 0;
tmp = in; in = out; out = tmp;
for(j = 0; j < nin; j++){
x1 = j;
x2 = (j+1) % nin;
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPYHI){
t = (V(x1)z - V(x1)y)/(V(x1)z - V(x1)y + V(x2)y - V(x2)z);
interpVertex(&out[nout++], &in[x1], &in[x2], t);
}
if((in[x2].clipFlags & CLIPYHI) == 0)
out[nout++] = in[x2];
}
// clip x 0
nin = nout; nout = 0;
tmp = in; in = out; out = tmp;
for(j = 0; j < nin; j++){
x1 = j;
x2 = (j+1) % nin;
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPXLO){
t = -V(x1)x/(V(x2)x - V(x1)x);
interpVertex(&out[nout++], &in[x1], &in[x2], t);
}
if((in[x2].clipFlags & CLIPXLO) == 0)
out[nout++] = in[x2];
}
// clip x z
nin = nout; nout = 0;
tmp = in; in = out; out = tmp;
for(j = 0; j < nin; j++){
x1 = j;
x2 = (j+1) % nin;
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPXHI){
t = (V(x1)z - V(x1)x)/(V(x1)z - V(x1)x + V(x2)x - V(x2)z);
interpVertex(&out[nout++], &in[x1], &in[x2], t);
}
if((in[x2].clipFlags & CLIPXHI) == 0)
out[nout++] = in[x2];
}
// Insert new triangles
x1 = mstate->numVertices;
for(j = 0; j < nout; j++){
x2 = mstate->numVertices++;
camverts[x2] = out[j];
cam2screen(&scrverts[x2], &camverts[x2]);
}
x2 = x1+1;
for(j = 0; j < nout-2; j++){
clipindices[0] = x1;
clipindices[1] = x2++;
clipindices[2] = x2;
clipindices += 3;
newNumPrims++;
}
}
mstate->numPrimitives = newNumPrims;
}
static int32
clipPoly(CamSpace3DVertex *in, int32 nin, CamSpace3DVertex *out, Plane *plane)
{
int32 j;
int32 nout;
int32 x1, x2;
float32 d1, d2, t;
nout = 0;
for(j = 0; j < nin; j++){
x1 = j;
x2 = (j+1) % nin;
d1 = dot(plane->normal, in[x1].camVertex) + plane->distance;
d2 = dot(plane->normal, in[x2].camVertex) + plane->distance;
if(d1*d2 < 0.0f){
t = d1/(d1 - d2);
interpVertex(&out[nout++], &in[x1], &in[x2], t);
}
if(d2 >= 0.0f)
out[nout++] = in[x2];
}
return nout;
}
static void
clipTriangles2(MeshState *mstate, CamSpace3DVertex *camverts, Im2DVertex *scrverts, uint16 *indices, uint16 *clipindices)
{
int32 i, j;
int32 x1, x2, x3;
int32 newNumPrims;
CamSpace3DVertex buf[18];
CamSpace3DVertex *in, *out;
int32 nout;
Camera *cam = (Camera*)engine->currentCamera;
Plane planes[6] = {
{ { 0.0f, 0.0f, 1.0f }, -cam->nearPlane }, // z = near
{ { 0.0f, 0.0f, -1.0f }, cam->farPlane }, // z = far
{ { -1.0f, 0.0f, 1.0f }, 0.0f }, // x = w
// { { 1.0f, 0.0f, 1.0f }, 0.0f }, // x = -w
{ { 1.0f, 0.0f, 0.0f }, 0.0f }, // x = 0
{ { 0.0f, -1.0f, 1.0f }, 0.0f }, // y = w
// { { 0.0f, 1.0f, 1.0f }, 0.0f } // y = -1
{ { 0.0f, 1.0f, 0.0f }, 0.0f } // y = 0
};
newNumPrims = 0;
for(i = 0; i < mstate->numPrimitives; i++, indices += 3){
x1 = indices[0];
x2 = indices[1];
x3 = indices[2];
if((camverts[x1].clipFlags |
camverts[x2].clipFlags |
camverts[x3].clipFlags) == 0){
// all inside
clipindices[0] = x1;
clipindices[1] = x2;
clipindices[2] = x3;
clipindices += 3;
newNumPrims++;
continue;
}
// set up triangle
in = &buf[0];
out = &buf[9];
in[0] = camverts[x1];
in[1] = camverts[x2];
in[2] = camverts[x3];
nout = 0;
// clip here
if(nout = clipPoly(in, 3, out, &planes[0]), nout == 0) continue;
if(nout = clipPoly(out, nout, in, &planes[1]), nout == 0) continue;
if(nout = clipPoly(in, nout, out, &planes[2]), nout == 0) continue;
if(nout = clipPoly(out, nout, in, &planes[3]), nout == 0) continue;
if(nout = clipPoly(in, nout, out, &planes[4]), nout == 0) continue;
if(nout = clipPoly(out, nout, in, &planes[5]), nout == 0) continue;
out = in;
// Insert new triangles
x1 = mstate->numVertices;
for(j = 0; j < nout; j++){
x2 = mstate->numVertices++;
camverts[x2] = out[j];
cam2screen(&scrverts[x2], &camverts[x2]);
}
x2 = x1+1;
for(j = 0; j < nout-2; j++){
clipindices[0] = x1;
clipindices[1] = x2++;
clipindices[2] = x2;
clipindices += 3;
newNumPrims++;
}
}
mstate->numPrimitives = newNumPrims;
}
static void
submitTriangles(RWDEVICE::Im2DVertex *scrverts, int32 numVerts, uint16 *indices, int32 numTris)
{
rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
if(dosoftras)
rastest_renderTriangles(scrverts, numVerts, indices, numTris);
else{
//int i;
//for(i = 0; i < numVerts; i++){
// scrverts[i].x = (int)(scrverts[i].x*16.0f) / 16.0f;
// scrverts[i].y = (int)(scrverts[i].y*16.0f) / 16.0f;
//}
im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, scrverts, numVerts,
indices, numTris*3);
}
}
static void
drawMesh(MeshState *mstate, ObjSpace3DVertex *objverts, uint16 *indices)
{
CamSpace3DVertex *camverts;
Im2DVertex *scrverts;
uint16 *cullindices, *clipindices;
uint32 numClip;
camverts = rwNewT(CamSpace3DVertex, mstate->numVertices, MEMDUR_FUNCTION);
scrverts = rwNewT(Im2DVertex, mstate->numVertices, MEMDUR_FUNCTION);
cullindices = rwNewT(uint16, mstate->numPrimitives*3, MEMDUR_FUNCTION);
transform(mstate, objverts, camverts, scrverts);
numClip = cullTriangles(mstate, camverts, indices, cullindices);
// int32 i;
// for(i = 0; i < mstate->numVertices; i++){
// if(camverts[i].clipFlags & CLIPX)
// camverts[i].color.red = 255;
// if(camverts[i].clipFlags & CLIPY)
// camverts[i].color.green = 255;
// if(camverts[i].clipFlags & CLIPZ)
// camverts[i].color.blue = 255;
// }
light(mstate, objverts, camverts);
// mstate->matCol.red = 255;
// mstate->matCol.green = 255;
// mstate->matCol.blue = 255;
postlight(mstate, camverts, scrverts);
// each triangle can have a maximum of 9 vertices (7 triangles) after clipping
// so resize to whatever we may need
camverts = rwResizeT(CamSpace3DVertex, camverts, mstate->numVertices + numClip*9, MEMDUR_FUNCTION);
scrverts = rwResizeT(Im2DVertex, scrverts, mstate->numVertices + numClip*9, MEMDUR_FUNCTION);
clipindices = rwNewT(uint16, mstate->numPrimitives*3 + numClip*7*3, MEMDUR_FUNCTION);
// clipTriangles(mstate, camverts, scrverts, cullindices, clipindices);
clipTriangles2(mstate, camverts, scrverts, cullindices, clipindices);
submitTriangles(scrverts, mstate->numVertices, clipindices, mstate->numPrimitives);
rwFree(camverts);
rwFree(scrverts);
rwFree(cullindices);
rwFree(clipindices);
}
static void
drawAtomic(Atomic *atomic)
{
MeshState mstate;
Matrix lightmat;
Geometry *geo;
MeshHeader *header;
InstanceData *inst;
int i;
Camera *cam = (Camera*)engine->currentCamera;
instanceAtomic(atomic);
mstate.obj2world = *atomic->getFrame()->getLTM();
mstate.obj2cam = mstate.obj2world;
mstate.obj2cam.transform(&cam->viewMatrix, COMBINEPOSTCONCAT);
Matrix::invert(&lightmat, &mstate.obj2world);
enumLights(&lightmat);
geo = atomic->geometry;
header = geo->meshHeader;
inst = ((InstanceDataHeader*)geo->instData)->inst;
for(i = 0; i < header->numMeshes; i++){
mstate.flags = geo->flags;
mstate.numVertices = inst->numVertices;
mstate.numPrimitives = inst->numIndices / 3;
mstate.surfProps = inst->material->surfaceProps;
mstate.matCol = inst->material->color;
drawMesh(&mstate, inst->vertices, inst->indices);
inst++;
}
}
void
tlTest(Clump *clump)
{
FORLIST(lnk, clump->atomics){
Atomic *a = Atomic::fromClump(lnk);
drawAtomic(a);
}
}
}
static Im2DVertex *clipverts;
static int32 numClipverts;
void
genIm3DTransform(void *vertices, int32 numVertices, Matrix *world)
{
Im3DVertex *objverts;
V3d pos;
Matrix xform;
Camera *cam;
int32 i;
objverts = (Im3DVertex*)vertices;
cam = (Camera*)engine->currentCamera;
int32 width = cam->frameBuffer->width;
int32 height = cam->frameBuffer->height;
xform = cam->viewMatrix;
if(world)
xform.transform(world, COMBINEPRECONCAT);
clipverts = rwNewT(Im2DVertex, numVertices, MEMDUR_EVENT);
numClipverts = numVertices;
for(i = 0; i < numVertices; i++){
V3d::transformPoints(&pos, &objverts[i].position, 1, &xform);
float32 recipZ = 1.0f/pos.z;
RGBA c = objverts[i].getColor();
clipverts[i].setScreenX(pos.x * recipZ * width);
clipverts[i].setScreenY(pos.y * recipZ * height);
clipverts[i].setScreenZ(recipZ * cam->zScale + cam->zShift);
clipverts[i].setCameraZ(pos.z);
clipverts[i].setRecipCameraZ(recipZ);
clipverts[i].setColor(c.red, c.green, c.blue, c.alpha);
clipverts[i].setU(objverts[i].u, recipZ);
clipverts[i].setV(objverts[i].v, recipZ);
}
}
void
genIm3DRenderIndexed(PrimitiveType prim, void *indices, int32 numIndices)
{
im2d::RenderIndexedPrimitive(prim, clipverts, numClipverts, indices, numIndices);
}
void
genIm3DEnd(void)
{
rwFree(clipverts);
clipverts = nil;
numClipverts = 0;
}

View file

@ -0,0 +1,26 @@
add_executable(ps2test
gs.h
main.cpp
mem.h
ps2.h
vu/defaultpipe.dsm
vu/skinpipe.dsm
vu/light.vu
vu/setup_persp.vu
)
target_link_libraries(ps2test
PRIVATE
librw::librw
kernel
)
librw_platform_target(ps2test INSTALL)
if(LIBRW_INSTALL)
install(TARGETS ps2test
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
endif()

437
vendor/librw/tools/ps2test/gs.h vendored Normal file
View file

@ -0,0 +1,437 @@
#define GS_NONINTERLACED 0
#define GS_INTERLACED 1
#define GS_NTSC 2
#define GS_PAL 3
#define GS_VESA1A 0x1a
#define GS_VESA1B 0x1b
#define GS_VESA1C 0x1c
#define GS_VESA1D 0x1d
#define GS_VESA2A 0x2a
#define GS_VESA2B 0x2b
#define GS_VESA2C 0x2c
#define GS_VESA2D 0x2d
#define GS_VESA2E 0x2e
#define GS_VESA3B 0x3b
#define GS_VESA3C 0x3c
#define GS_VESA3D 0x3d
#define GS_VESA3E 0x3e
#define GS_VESA4A 0x4a
#define GS_VESA4B 0x4b
#define GS_DTV480P 0x50
#define GS_FIELD 0
#define GS_FRAME 1
#define GS_PSMCT32 0
#define GS_PSMCT24 1
#define GS_PSMCT16 2
#define GS_PSMCT16S 10
#define GS_PS_GPU24 18
#define GS_PSMZ32 0
#define GS_PSMZ24 1
#define GS_PSMZ16 2
#define GS_PSMZ16S 10
#define GS_ZTST_NEVER 0
#define GS_ZTST_ALWAYS 1
#define GS_ZTST_GREATER 2
#define GS_ZTST_GEQUAL 3
#define GS_PRIM_POINT 0
#define GS_PRIM_LINE 1
#define GS_PRIM_LINE_STRIP 2
#define GS_PRIM_TRI 3
#define GS_PRIM_TRI_STRIP 4
#define GS_PRIM_TRI_FAN 5
#define GS_PRIM_SPRITE 6
#define GS_PRIM_NO_SPEC 7
#define GS_IIP_FLAT 0
#define GS_IIP_GOURAUD 1
/* GS general purpose registers */
#define GS_PRIM 0x00
#define GS_RGBAQ 0x01
#define GS_ST 0x02
#define GS_UV 0x03
#define GS_XYZF2 0x04
#define GS_XYZ2 0x05
#define GS_TEX0_1 0x06
#define GS_TEX0_2 0x07
#define GS_CLAMP_1 0x08
#define GS_CLAMP_2 0x09
#define GS_FOG 0x0a
#define GS_XYZF3 0x0c
#define GS_XYZ3 0x0d
#define GS_TEX1_1 0x14
#define GS_TEX1_2 0x15
#define GS_TEX2_1 0x16
#define GS_TEX2_2 0x17
#define GS_XYOFFSET_1 0x18
#define GS_XYOFFSET_2 0x19
#define GS_PRMODECONT 0x1a
#define GS_PRMODE 0x1b
#define GS_TEXCLUT 0x1c
#define GS_SCANMSK 0x22
#define GS_MIPTBP1_1 0x34
#define GS_MIPTBP1_2 0x35
#define GS_MIPTBP2_1 0x36
#define GS_MIPTBP2_2 0x37
#define GS_TEXA 0x3b
#define GS_FOGCOL 0x3d
#define GS_TEXFLUSH 0x3f
#define GS_SCISSOR_1 0x40
#define GS_SCISSOR_2 0x41
#define GS_ALPHA_1 0x42
#define GS_ALPHA_2 0x43
#define GS_DIMX 0x44
#define GS_DTHE 0x45
#define GS_COLCLAMP 0x46
#define GS_TEST_1 0x47
#define GS_TEST_2 0x48
#define GS_PABE 0x49
#define GS_FBA_1 0x4a
#define GS_FBA_2 0x4b
#define GS_FRAME_1 0x4c
#define GS_FRAME_2 0x4d
#define GS_ZBUF_1 0x4e
#define GS_ZBUF_2 0x4f
#define GS_BITBLTBUF 0x50
#define GS_TRXPOS 0x51
#define GS_TRXREG 0x52
#define GS_TRXDIR 0x53
#define GS_HWREG 0x54
#define GS_SIGNAL 0x60
#define GS_FINISH 0x61
#define GS_LABEL 0x62
typedef union
{
struct {
uint64 EN1 : 1;
uint64 EN2 : 1;
uint64 CRTMD : 3;
uint64 MMOD : 1;
uint64 AMOD : 1;
uint64 SLBG : 1;
uint64 ALP : 8;
} f;
uint64 d;
} GsPmode;
#define GS_MAKE_PMODE(EN1,EN2,MMOD,AMOD,SLBG,ALP) \
(BIT64(EN1,0) | BIT64(EN2,1) | BIT64(1,2) | \
BIT64(MMOD,5) | BIT64(AMOD,6) | BIT64(SLBG,7) | BIT64(ALP,8))
typedef union
{
struct {
uint64 INT : 1;
uint64 FFMD : 1;
uint64 DPMS : 2;
} f;
uint64 d;
} GsSmode2;
#define GS_MAKE_SMODE2(INT,FFMD,DPMS) \
(BIT64(INT,0) | BIT64(FFMD,1) | BIT64(DPMS,2))
typedef union
{
struct {
uint64 FBP : 9;
uint64 FBW : 6;
uint64 PSM : 5;
uint64 : 12;
uint64 DBX : 11;
uint64 DBY : 11;
} f;
uint64 d;
} GsDispfb;
#define GS_MAKE_DISPFB(FBP,FBW,PSM,DBX,DBY) \
(BIT64(FBP,0) | BIT64(FBW,9) | BIT64(PSM,15) | \
BIT64(DBX,32) | BIT64(DBY,43))
typedef union
{
struct {
uint64 DX : 12;
uint64 DY : 11;
uint64 MAGH : 4;
uint64 MAGV : 2;
uint64 : 3;
uint64 DW : 12;
uint64 DH : 11;
} f;
uint64 d;
} GsDisplay;
#define GS_MAKE_DISPLAY(DX,DY,MAGH,MAGV,DW,DH) \
(BIT64(DX,0) | BIT64(DY,12) | BIT64(MAGH,23) | \
BIT64(MAGV,27) | BIT64(DW,32) | BIT64(DH,44))
typedef union
{
struct {
uint64 EXBP : 14;
uint64 EXBW : 6;
uint64 FBIN : 2;
uint64 WFFMD : 1;
uint64 EMODA : 2;
uint64 EMODC : 2;
uint64 : 5;
uint64 WDX : 11;
uint64 WDY : 11;
} f;
uint64 d;
} GsExtbuf;
#define GS_MAKE_EXTBUF(EXBP,EXBW,FBIN,WFFMD,EMODA,EMODC,WDX,WDY) \
(BIT64(EXBP,0) | BIT64(EXBW,14) | BIT64(FBIN,20) | \
BIT64(WFFMD,22) | BIT64(EMODA,23) | BIT64(EMODC,25) | \
BIT64(WDX,32) | BIT64(WDY,43))
typedef union
{
struct {
uint64 SX : 12;
uint64 SY : 11;
uint64 SMPH : 4;
uint64 SMPV : 2;
uint64 : 3;
uint64 WW : 12;
uint64 WH : 11;
} f;
uint64 d;
} GsExtdata;
#define GS_MAKE_EXTDATA(SX,SY,SMPH,SMPV,WW,WH) \
(BIT64(SX,0) | BIT64(SY,12) | BIT64(SMPH,23) | \
BIT64(SMPV,27) | BIT64(WW,32) | BIT64(WH,44))
typedef union
{
struct {
uint64 WRITE : 1;
} f;
uint64 d;
} GsExtwrite;
typedef union
{
struct {
uint64 R : 8;
uint64 G : 8;
uint64 B : 8;
} f;
uint64 d;
} GsBgcolor;
#define GS_MAKE_BGCOLOR(R,G,B) \
(BIT64(R,0) | BIT64(G,8) | BIT64(B,16))
typedef union
{
struct {
uint64 SIGNAL : 1;
uint64 FINISH : 1;
uint64 HSINT : 1;
uint64 VSINT : 1;
uint64 EDWINT : 1;
uint64 : 3;
uint64 FLUSH : 1;
uint64 RESET : 1;
uint64 : 2;
uint64 NFIELD : 1;
uint64 FIELD : 1;
uint64 FIFO : 2;
uint64 REV : 8;
uint64 ID : 8;
} f;
uint64 d;
} GsCsr;
#define GS_CSR_SIGNAL_O 0
#define GS_CSR_FINISH_O 1
#define GS_CSR_HSINT_O 2
#define GS_CSR_VSINT_O 3
#define GS_CSR_EDWINT_O 4
#define GS_CSR_FLUSH_O 8
#define GS_CSR_RESET_O 9
#define GS_CSR_NFIELD_O 12
#define GS_CSR_FIELD_O 13
#define GS_CSR_FIFO_O 14
#define GS_CSR_REV_O 16
#define GS_CSR_ID_O 24
typedef union
{
struct {
uint64 : 8;
uint64 SIGMSK : 1;
uint64 FINISHMSK : 1;
uint64 HSMSKMSK : 1;
uint64 VSMSKMSK : 1;
uint64 EDWMSKMSK : 1;
} f;
uint64 d;
} GsImr;
typedef union
{
struct {
uint64 DIR : 1;
} f;
uint64 d;
} GsBusdir;
typedef union
{
struct {
uint64 SIGID : 32;
uint64 LBLID : 32;
} f;
uint64 d;
} GsSiglblid;
typedef union
{
struct {
uint64 FBP : 9;
uint64 : 7;
uint64 FBW : 6;
uint64 : 2;
uint64 PSM : 6;
uint64 : 2;
uint64 FBMSK : 32;
} f;
uint64 d;
} GsFrame;
#define GS_MAKE_FRAME(FBP,FBW,PSM,FBMASK) \
(BIT64(FBP,0) | BIT64(FBW,16) | BIT64(PSM,24) | BIT64(FBMASK,32))
typedef union
{
struct {
uint64 ZBP : 9;
uint64 : 15;
uint64 PSM : 4;
uint64 : 4;
uint64 ZMSDK : 1;
} f;
uint64 d;
} GsZbuf;
#define GS_MAKE_ZBUF(ZBP,PSM,ZMSK) \
(BIT64(ZBP,0) | BIT64(PSM,24) | BIT64(ZMSK,32))
typedef union
{
struct {
uint64 OFX : 16;
uint64 : 16;
uint64 OFY : 16;
} f;
uint64 d;
} GsXyOffset;
#define GS_MAKE_XYOFFSET(OFX,OFY) \
(BIT64(OFX,0) | BIT64(OFY,32))
typedef union
{
struct {
uint64 SCAX0 : 11;
uint64 : 5;
uint64 SCAX1 : 11;
uint64 : 5;
uint64 SCAY0 : 11;
uint64 : 5;
uint64 SCAY1 : 11;
} f;
uint64 d;
} GsScissor;
#define GS_MAKE_SCISSOR(SCAX0,SCAX1,SCAY0,SCAY1) \
(BIT64(SCAX0,0) | BIT64(SCAX1,16) | BIT64(SCAY0,32) | BIT64(SCAY1,48))
#define GS_MAKE_TEST(ATE,ATST,AREF,AFAIL,DATE,DATM,ZTE,ZTST) \
(BIT64(ATE,0) | BIT64(ATST,1) | BIT64(AREF,4) | BIT64(AFAIL,12) | \
BIT64(DATE,14) | BIT64(DATM,15) | BIT64(ZTE,16) | BIT64(ZTST,17))
#define GS_MAKE_PRIM(PRIM,IIP,TME,FGE,ABE,AA1,FST,CTXT,FIX) \
(BIT64(PRIM,0) | BIT64(IIP,3) | BIT64(TME,4) | BIT64(FGE,5) | \
BIT64(ABE,6) | BIT64(AA1,7) | BIT64(FST,8) | BIT64(CTXT,9) | BIT64(FIX,10))
#define GS_MAKE_RGBAQ(R,G,B,A,Q) \
(BIT64(R,0) | BIT64(G,8) | BIT64(B,16) | BIT64(A,24) | BIT64(Q,32))
#define GS_MAKE_XYZ(X,Y,Z) \
(BIT64(X,0) | BIT64(Y,16) | BIT64(Z,32))
#define GIF_PACKED 0
#define GIF_REGLIST 1
#define GIF_IMAGE 2
#define GIF_MAKE_TAG(NLOOP,EOP,PRE,PRIM,FLG,NREG) \
(BIT64(NLOOP,0) | BIT64(EOP,15) | BIT64(PRE,46) | \
BIT64(PRIM,47) | BIT64(FLG,58) | BIT64(NREG,60))
/* This is global and not tied to a user context because
* it is set up by kernel functions and not really changed
* afterwards. */
typedef struct GsCrtState GsCrtState;
struct GsCrtState
{
short inter, mode, ff;
};
extern GsCrtState gsCrtState;
typedef struct GsDispCtx GsDispCtx;
struct GsDispCtx
{
// two circuits
GsPmode pmode;
GsDispfb dispfb1;
GsDispfb dispfb2;
GsDisplay display1;
GsDisplay display2;
GsBgcolor bgcolor;
};
typedef struct GsDrawCtx GsDrawCtx;
struct GsDrawCtx
{
//two contexts
uint128 gifTag;
GsFrame frame1;
uint64 ad_frame1;
GsFrame frame2;
uint64 ad_frame2;
GsZbuf zbuf1;
uint64 ad_zbuf1;
GsZbuf zbuf2;
uint64 ad_zbuf2;
GsXyOffset xyoffset1;
uint64 ad_xyoffset1;
GsXyOffset xyoffset2;
uint64 ad_xyoffset2;
GsScissor scissor1;
uint64 ad_scissor1;
GsScissor scissor2;
uint64 ad_scissor2;
};
typedef struct GsCtx GsCtx;
struct GsCtx
{
// display context; two buffers
GsDispCtx disp[2];
// draw context; two buffers
GsDrawCtx draw[2];
};

787
vendor/librw/tools/ps2test/main.cpp vendored Normal file
View file

@ -0,0 +1,787 @@
#include <cstdio>
#include <cassert>
#define PAL
#include <rw.h>
using rw::uint8;
using rw::uint16;
using rw::uint32;
using rw::uint64;
using rw::int8;
using rw::int16;
using rw::int32;
using rw::int64;
using rw::bool32;
using rw::float32;
typedef uint8 uchar;
typedef uint16 ushort;
typedef uint32 uint;
#define WIDTH 640
#ifdef PAL
#define HEIGHT 512
#define VMODE GS_PAL
#else
#define HEIGHT 448
#define VMODE GS_NTSC
#endif
#include "ps2.h"
// getting undefined references otherwise :/
int *__errno() { return &errno; }
// NONINTERLACED and FRAME have half of the FIELD vertical resolution!
// NONINTERLACED has half the vertical units
uint128 packetbuf[128];
uint128 vuXYZScale;
uint128 vuXYZOffset;
extern uint32 geometryCall[];
extern uint32 skinPipe[];
uint128 *curVifPtr;
uint128 lightpacket[128];
int32 numLightQ;
rw::World *world;
rw::Camera *camera;
int frames;
void
printquad(uint128 p)
{
uint64 *lp;
lp = (uint64*)&p;
printf("%016lx %016lx\n", lp[1], lp[0]);
}
void
printquad4(uint128 p)
{
uint32 *lp;
lp = (uint32*)&p;
printf("%08x %08x %08x %08x\n", lp[0], lp[1], lp[2], lp[3]);
}
void
dump4(uint128 *p, int n)
{
printf("data at %p\n", p);
while(n--)
printquad4(*p++);
}
struct DmaChannel {
uint32 chcr; uint32 pad0[3];
uint32 madr; uint32 pad1[3];
uint32 qwc; uint32 pad2[3];
uint32 tadr; uint32 pad3[3];
uint32 asr0; uint32 pad4[3];
uint32 asr1; uint32 pad5[3];
uint32 pad6[8];
uint32 sadr;
};
static struct DmaChannel *dmaChannels[] = {
(struct DmaChannel *) &D0_CHCR,
(struct DmaChannel *) &D1_CHCR,
(struct DmaChannel *) &D2_CHCR,
(struct DmaChannel *) &D3_CHCR,
(struct DmaChannel *) &D4_CHCR,
(struct DmaChannel *) &D5_CHCR,
(struct DmaChannel *) &D6_CHCR,
(struct DmaChannel *) &D7_CHCR,
(struct DmaChannel *) &D8_CHCR,
(struct DmaChannel *) &D9_CHCR
};
void
dmaReset(void)
{
/* don't clear the SIF channels */
int doclear[] = { 1, 1, 1, 1, 1, 0, 0, 0, 1, 1 };
int i;
D_CTRL = 0;
for(i = 0; i < 10; i++)
if(doclear[i]){
dmaChannels[i]->chcr = 0;
dmaChannels[i]->madr = 0;
dmaChannels[i]->qwc = 0;
dmaChannels[i]->tadr = 0;
dmaChannels[i]->asr0 = 0;
dmaChannels[i]->asr1 = 0;
dmaChannels[i]->sadr = 0;
}
D_CTRL = 1;
}
void
waitDMA(volatile uint32 *chcr)
{
while(*chcr & (1<<8));
}
void
qwcpy(uint128 *dst, uint128 *src, int n)
{
while(n--) *dst++ = *src++;
}
void
toGIF(void *src, int n)
{
FlushCache(0);
D2_QWC = n;
D2_MADR = (uint32)src;
D2_CHCR = 1<<8;
waitDMA(&D2_CHCR);
}
void
toGIFchain(void *src)
{
FlushCache(0);
D2_QWC = 0;
D2_TADR = (uint32)src & 0x0FFFFFFF;
D2_CHCR = 1<<0 | 1<<2 | 1<<6 | 1<<8;
waitDMA(&D2_CHCR);
}
void
toVIF1chain(void *src)
{
FlushCache(0);
D1_QWC = 0;
D1_TADR = (uint32)src & 0x0FFFFFFF;
D1_CHCR = 1<<0 | 1<<2 | 1<<6 | 1<<8;
waitDMA(&D1_CHCR);
}
GsCrtState gsCrtState;
int psmsizemap[64] = {
4, // GS_PSMCT32
4, // GS_PSMCT24
2, // GS_PSMCT16
0, 0, 0, 0, 0, 0, 0,
2, // GS_PSMCT16S
0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4, // GS_PSMZ32
4, // GS_PSMZ24
2, // GS_PSMZ16
2, // GS_PSMZ16S
0, 0, 0, 0, 0
};
void
GsResetCrt(uchar inter, uchar mode, uchar ff)
{
gsCrtState.inter = inter;
gsCrtState.mode = mode;
gsCrtState.ff = ff;
GS_CSR = 1 << GS_CSR_RESET_O;
__asm__("sync.p; nop");
GsPutIMR(0xff00);
SetGsCrt(gsCrtState.inter, gsCrtState.mode, gsCrtState.ff);
}
uint gsAllocPtr = 0;
void
GsInitDispCtx(GsDispCtx *disp, int width, int height, int psm)
{
int magh, magv;
int dx, dy;
int dw, dh;
dx = gsCrtState.mode == GS_NTSC ? 636 : 656;
dy = gsCrtState.mode == GS_NTSC ? 25 : 36;
magh = 2560/width - 1;
magv = 0;
dw = 2560-1;
dh = height-1;
if(gsCrtState.inter == GS_INTERLACED){
dy *= 2;
if(gsCrtState.ff == GS_FRAME)
dh = (dh+1)*2-1;
}
disp->pmode.d = GS_MAKE_PMODE(0, 1, 1, 1, 0, 0x00);
// disp->bgcolor.d = 0x404040;
disp->bgcolor.d = 0x000000;
disp->dispfb1.d = 0;
disp->dispfb2.d = GS_MAKE_DISPFB(0, width/64, psm, 0, 0);
disp->display1.d = 0;
disp->display2.d = GS_MAKE_DISPLAY(dx, dy, magh, magv, dw, dh);
}
void
GsPutDispCtx(GsDispCtx *disp)
{
GS_PMODE = disp->pmode.d;
GS_DISPFB1 = disp->dispfb1.d;
GS_DISPLAY1 = disp->display1.d;
GS_DISPFB2 = disp->dispfb2.d;
GS_DISPLAY2 = disp->display2.d;
GS_BGCOLOR = disp->bgcolor.d;
}
void
GsInitDrawCtx(GsDrawCtx *draw, int width, int height, int psm, int zpsm)
{
MAKE128(draw->gifTag, 0xe,
GIF_MAKE_TAG(8, 1, 0, 0, GIF_PACKED, 1));
draw->frame1.d = GS_MAKE_FRAME(0, width/64, psm, 0);
draw->ad_frame1 = GS_FRAME_1;
draw->frame2.d = draw->frame1.d;
draw->ad_frame2 = GS_FRAME_2;
draw->zbuf1.d = GS_MAKE_ZBUF(0, zpsm, 0);
draw->ad_zbuf1 = GS_ZBUF_1;
draw->zbuf2.d = draw->zbuf1.d;
draw->ad_zbuf2 = GS_ZBUF_2;
draw->xyoffset1.d = GS_MAKE_XYOFFSET(2048<<4, 2048<<4);
draw->ad_xyoffset1 = GS_XYOFFSET_1;
draw->xyoffset2.d = draw->xyoffset1.d;
draw->ad_xyoffset2 = GS_XYOFFSET_2;
draw->scissor1.d = GS_MAKE_SCISSOR(0, width-1, 0, height-1);
draw->ad_scissor1 = GS_SCISSOR_1;
draw->scissor2.d = draw->scissor1.d;
draw->ad_scissor2 = GS_SCISSOR_2;
}
void
GsPutDrawCtx(GsDrawCtx *draw)
{
// printquad(*(uint128*)&draw->frame1);
toGIF(draw, 9);
}
void
GsInitCtx(GsCtx *ctx, int width, int height, int psm, int zpsm)
{
uint fbsz, zbsz;
uint fbp, zbp;
fbsz = (width*height*psmsizemap[psm] + 2047)/2048;
zbsz = (width*height*psmsizemap[0x30|zpsm] + 2047)/2048;
gsAllocPtr = 2*fbsz + zbsz;
fbp = fbsz;
zbp = fbsz*2;
GsInitDispCtx(&ctx->disp[0], width, height, psm);
GsInitDispCtx(&ctx->disp[1], width, height, psm);
GsInitDrawCtx(&ctx->draw[0], width, height, psm, zpsm);
GsInitDrawCtx(&ctx->draw[1], width, height, psm, zpsm);
ctx->disp[1].dispfb2.f.FBP = fbp/4;
ctx->draw[0].frame1.f.FBP = fbp/4;
ctx->draw[0].frame2.f.FBP = fbp/4;
ctx->draw[0].zbuf1.f.ZBP = zbp/4;
ctx->draw[0].zbuf2.f.ZBP = zbp/4;
ctx->draw[1].zbuf1.f.ZBP = zbp/4;
ctx->draw[1].zbuf2.f.ZBP = zbp/4;
}
void
initrender(void)
{
uint128 *p, tmp;
p = packetbuf;
MAKE128(tmp, 0xe, GIF_MAKE_TAG(2, 1, 0, 0, GIF_PACKED, 1));
*p++ = tmp;
MAKE128(tmp, GS_PRMODECONT, 1);
*p++ = tmp;
MAKE128(tmp, GS_COLCLAMP, 1);
*p++ = tmp;
toGIF(packetbuf, 3);
}
void
clearscreen(int r, int g, int b)
{
int x, y;
uint128 *p, tmp;
p = packetbuf;
x = (2048 + WIDTH)<<4;
y = (2048 + HEIGHT)<<4;
MAKE128(tmp, 0xe, GIF_MAKE_TAG(5, 1, 0, 0, GIF_PACKED, 1));
*p++ = tmp;
MAKE128(tmp, GS_TEST_1, GS_MAKE_TEST(0, 0, 0, 0, 0, 0, 1, 1));
*p++ = tmp;
MAKE128(tmp, GS_PRIM, GS_MAKE_PRIM(GS_PRIM_SPRITE,0,0,0,0,0,0,0,0));
*p++ = tmp;
MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(r, g, b, 0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(2048<<4, 2048<<4, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x, y, 0));
*p++ = tmp;
toGIF(packetbuf, 6);
}
void
drawtest(void)
{
int x0, x1, x2, x3;
int y0, y1, y2;
uint128 *p, tmp;
int n;
x0 = 2048<<4;
x1 = (2048 + 210)<<4;
x2 = (2048 + 430)<<4;
x3 = (2048 + 640)<<4;
y0 = 2048<<4;
y1 = (2048 + 224)<<4;
y2 = (2048 + 448)<<4;
n = 2 + 3*7;
p = packetbuf;
MAKEQ(tmp, 0x70000000 | n+1, 0, 0, 0);
*p++ = tmp;
MAKE128(tmp, 0xe, GIF_MAKE_TAG(n, 1, 0, 0, GIF_PACKED, 1));
*p++ = tmp;
MAKE128(tmp, GS_TEST_1, GS_MAKE_TEST(0, 0, 0, 0, 0, 0, 1, 1));
*p++ = tmp;
MAKE128(tmp, GS_PRIM, GS_MAKE_PRIM(GS_PRIM_SPRITE,0,0,0,0,0,0,0,0));
*p++ = tmp;
MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(255, 0, 0, 0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x0, y0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x1, y1, 0));
*p++ = tmp;
MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(0, 255, 0, 0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x1, y0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x2, y1, 0));
*p++ = tmp;
MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(0, 0, 255, 0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x2, y0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x3, y1, 0));
*p++ = tmp;
MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(0, 255, 255, 0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x0, y1, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x1, y2, 0));
*p++ = tmp;
MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(255, 0, 255, 0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x1, y1, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x2, y2, 0));
*p++ = tmp;
MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(255, 255, 0, 0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x2, y1, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x3, y2, 0));
*p++ = tmp;
MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(255, 255, 255, 0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ((2048+20)<<4, y0, 0));
*p++ = tmp;
MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x3, (2048+20)<<4, 0));
*p++ = tmp;
toGIFchain(packetbuf);
}
void
drawtri(void)
{
uint128 *p, tmp;
uint32 *ip;
int nverts, n;
nverts = 3;
n = 2*nverts;
p = packetbuf;
MAKEQ(tmp, 0x70000000 | n+1, 0, 0, 0);
*p++ = tmp;
MAKE128(tmp, (0x5<<4) | 0x1,
GIF_MAKE_TAG(nverts, 1, 1, GS_MAKE_PRIM(GS_PRIM_TRI, 1, 0, 0, 0, 0, 0, 0, 0), GIF_PACKED, 2));
*p++ = tmp;
MAKEQ(tmp, 255, 0, 0, 0);
*p++ = tmp;
MAKEQ(tmp, (2048+85)<<4, (2048+70)<<4, 0, 0);
*p++ = tmp;
MAKEQ(tmp, 0, 255, 0, 0);
*p++ = tmp;
MAKEQ(tmp, (2048+260)<<4, (2048+200)<<4, 0, 0);
*p++ = tmp;
MAKEQ(tmp, 0, 0, 255, 0);
*p++ = tmp;
MAKEQ(tmp, (2048+180)<<4, (2048+350)<<4, 0, 0);
*p++ = tmp;
toGIFchain(packetbuf);
}
void
printMatrix(rw::Matrix *m)
{
rw::V3d *x = &m->right;
rw::V3d *y = &m->up;
rw::V3d *z = &m->at;
rw::V3d *w = &m->pos;
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"
" %08x == flags\n",
x->x, y->x, z->x, w->x,
x->y, y->y, z->y, w->y,
x->z, y->z, z->z, w->z,
0.0f, 0.0f, 0.0f, 1.0f,
m->flags);
}
// This is not proper data, just for testing
void
setupLight(rw::Atomic *atomic)
{
using namespace rw;
Matrix *lightmat;
float32 *lp;
numLightQ = 0;
lp = (float32*)lightpacket;
// TODO: this is the wrong matrix. we actually want to
// transform the light, not all normals.
lightmat = atomic->getFrame()->getLTM();
*lp++ = lightmat->right.x;
*lp++ = lightmat->right.y;
*lp++ = lightmat->right.z;
*lp++ = 0.0f;
*lp++ = lightmat->up.x;
*lp++ = lightmat->up.y;
*lp++ = lightmat->up.z;
*lp++ = 0.0f;
*lp++ = lightmat->at.x;
*lp++ = lightmat->at.y;
*lp++ = lightmat->at.z;
*lp++ = 0.0f;
*lp++ = lightmat->pos.x;
*lp++ = lightmat->pos.y;
*lp++ = lightmat->pos.z;
*lp++ = 1.0f;
// TODO: make a proper light block
// ambient
*lp++ = 80.0f;
*lp++ = 80.0f;
*lp++ = 80.0f;
*lp++ = 0.0f;
// directional
*lp++ = 0.5f;
*lp++ = -0.5f;
*lp++ = -0.7071f;
*lp++ = 0.0f;
numLightQ = 6;
}
void
setupTransform(rw::Atomic *atomic, rw::Matrix *trans)
{
rw::Matrix::mult(trans, atomic->getFrame()->getLTM(), &camera->viewMatrix);
}
enum {
DMAcnt = 0x10000000,
DMAref = 0x30000000,
DMAcall = 0x50000000,
DMAret = 0x60000000,
DMAend = 0x70000000,
V4_32 = 0x6C
};
#define UNPACK(type, nq, offset) ((type)<<24 | (nq)<<16 | (offset))
#define STCYCL(WL,CL) (0x01000000 | (WL)<<8 | (CL))
void
drawAtomic(rw::Atomic *atomic)
{
using namespace rw;
Matrix trans;
Geometry *geo;
ps2::ObjPipeline *pipe;
ps2::MatPipeline *matpipe;
Material *material;
uint128 tmp, *lp;
uint32 *vec;
RGBAf color;
int i;
geo = atomic->geometry;
pipe = (ps2::ObjPipeline*)atomic->getPipeline();
if(pipe->platform != PLATFORM_PS2)
return;
setupLight(atomic);
setupTransform(atomic, &trans);
curVifPtr = packetbuf;
// upload lights
MAKEQ(tmp, DMAcnt | numLightQ+8, 0, STCYCL(4,4), UNPACK(V4_32, numLightQ, 0x3d0));
*curVifPtr++ = tmp;
for(lp = lightpacket; numLightQ--;)
*curVifPtr++ = *lp++;
// upload transformation matrix
MAKEQ(tmp, 0, 0, STCYCL(4,4), UNPACK(V4_32, 4, 0x3f0));
*curVifPtr++ = tmp;
vec = (uint32*)&trans.right;
MAKEQ(tmp, vec[0], vec[1], vec[2], vec[2]);
*curVifPtr++ = tmp;
vec = (uint32*)&trans.up;
MAKEQ(tmp, vec[0], vec[1], vec[2], vec[2]);
*curVifPtr++ = tmp;
vec = (uint32*)&trans.at;
MAKEQ(tmp, vec[0], vec[1], vec[2], vec[2]);
*curVifPtr++ = tmp;
vec = (uint32*)&trans.pos;
MAKEQ(tmp, vec[0], vec[1], vec[2], vec[2]);
*curVifPtr++ = tmp;
// upload camera/screen info
MAKEQ(tmp, 0, 0, STCYCL(4,4), UNPACK(V4_32, 2, 0x3f7));
*curVifPtr++ = tmp;
*curVifPtr++ = vuXYZScale;
*curVifPtr++ = vuXYZOffset;
assert(geo->instData != NULL);
rw::ps2::InstanceDataHeader *instData =
(rw::ps2::InstanceDataHeader*)geo->instData;
rw::MeshHeader *meshHeader = geo->meshHeader;
rw::Mesh *mesh;
for(i = 0; i < instData->numMeshes; i++){
material = instData->instanceMeshes[i].material;
matpipe = pipe->groupPipeline;
if(matpipe == nil)
matpipe = (ps2::MatPipeline*)material->pipeline;
if(matpipe == nil)
matpipe = ps2::defaultMatPipe;
// call vu code
MAKEQ(tmp, DMAcall, (uint32)skinPipe, 0, 0);
*curVifPtr++ = tmp;
// unpack GIF tag, material color, surface properties
MAKEQ(tmp, DMAcnt | 3, 0, STCYCL(4,4), UNPACK(V4_32, 3, 0x3fa));
*curVifPtr++ = tmp;
MAKE128(tmp, 0x412,
GIF_MAKE_TAG(0, 1, 1, GS_MAKE_PRIM(GS_PRIM_TRI_STRIP,1,0,0,0,0,0,0,0), GIF_PACKED, 3));
*curVifPtr++ = tmp;
convColor(&color, &material->color);
color.alpha *= 128.0f/255.0f;
MAKEQ(tmp, *(uint32*)&color.red, *(uint32*)&color.green,
*(uint32*)&color.blue, *(uint32*)&color.alpha);
*curVifPtr++ = tmp;
MAKEQ(tmp, *(uint32*)&material->surfaceProps.ambient,
*(uint32*)&material->surfaceProps.specular,
*(uint32*)&material->surfaceProps.diffuse,
0.0f); // extra
*curVifPtr++ = tmp;
// call geometry
MAKEQ(tmp, DMAcall, (uint32)instData->instanceMeshes[i].data, 0x03000000, 0x02000000 | matpipe->vifOffset);
*curVifPtr++ = tmp;
}
MAKEQ(tmp, DMAend, 0, 0, 0);
*curVifPtr++ = tmp;
// for(lp = packetbuf; lp < curVifPtr; lp++)
// printquad4(*lp);
toVIF1chain(packetbuf);
}
void
beginCamera(void)
{
uint128 *p, tmp;
float32 *f;
p = packetbuf;
MAKE128(tmp, 0xe, GIF_MAKE_TAG(2, 1, 0, 0, GIF_PACKED, 1));
*p++ = tmp;
MAKE128(tmp, GS_XYOFFSET_1, GS_MAKE_XYOFFSET(2048-WIDTH/2 <<4, 2048-HEIGHT/2 <<4));
*p++ = tmp;
MAKE128(tmp, GS_TEST_1, GS_MAKE_TEST(0, 0, 0, 0, 0, 0, 1, 2));
*p++ = tmp;
toGIF(packetbuf, 3);
f = (float32*)&vuXYZScale;
f[0] = WIDTH;
f[1] = HEIGHT;
f[2] = camera->zScale;
f[3] = 0.0f;
f = (float32*)&vuXYZOffset;
f[0] = 2048.0f;
f[1] = 2048.0f;
f[2] = camera->zShift;
f[3] = 0.0f;
}
rw::EngineOpenParams engineOpenParams;
void
pluginattach(void)
{
rw::ps2::registerPDSPlugin(40);
rw::ps2::registerPluginPDSPipes();
rw::registerMeshPlugin();
rw::registerNativeDataPlugin();
rw::registerAtomicRightsPlugin();
rw::registerMaterialRightsPlugin();
rw::xbox::registerVertexFormatPlugin();
rw::registerSkinPlugin();
rw::registerHAnimPlugin();
rw::registerMatFXPlugin();
rw::registerUVAnimPlugin();
rw::ps2::registerADCPlugin();
}
bool32
initrw(void)
{
rw::version = 0x34000;
rw::platform = rw::PLATFORM_PS2;
if(!rw::Engine::init())
return 0;
pluginattach();
if(!rw::Engine::open(&engineOpenParams))
return 0;
if(!rw::Engine::start())
return 0;
rw::Texture::setLoadTextures(0);
rw::TexDictionary::setCurrent(rw::TexDictionary::create());
rw::Image::setSearchPath(".");
world = rw::World::create();
camera = rw::Camera::create();
camera->frameBuffer = rw::Raster::create(WIDTH, HEIGHT, 0, rw::Raster::CAMERA);
camera->zBuffer = rw::Raster::create(WIDTH, HEIGHT, 0, rw::Raster::ZBUFFER);
camera->setFrame(rw::Frame::create());
rw::V3d t = { 0.0f, 0.0f, -4.0f };
// rw::V3d t = { 0.0f, 0.0f, -40.0f };
camera->getFrame()->translate(&t, rw::COMBINEPOSTCONCAT);
rw::V3d axis = { 0.0f, 1.0f, 0.0f };
camera->getFrame()->rotate(&axis, 40.0f, rw::COMBINEPOSTCONCAT);
camera->setNearPlane(0.1f);
camera->setFarPlane(450.0f);
camera->setFOV(60.0f, 4.0f/3.0f);
world->addCamera(camera);
return 1;
}
int vsynchInt = 0;
int
vsynch(int id)
{
vsynchInt = 1;
frames++;
ExitHandler();
return 0;
}
int
main()
{
FlushCache(0);
if(!initrw()){
printf("init failed!\n");
for(;;);
}
rw::uint32 len;
rw::uint8 *data = rw::getFileContents("host:player.DFF", &len);
// rw::uint8 *data = rw::getFileContents("host:od_newscafe_dy.dff", &len);
rw::StreamMemory in;
in.open(data, len);
rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL);
rw::Clump *clump = rw::Clump::streamRead(&in);
in.close();
rwFree(data);
GsCtx gsCtx;
dmaReset();
// GsResetCrt(GS_NONINTERLACED, GS_NTSC, 0);
// GsInitCtx(&gsCtx, 640, 224, GS_PSMCT32, GS_PSMZ32);
// GsResetCrt(GS_INTERLACED, GS_NTSC, GS_FRAME);
// GsInitCtx(&gsCtx, 640, 224, GS_PSMCT32, GS_PSMZ32);
GsResetCrt(GS_INTERLACED, VMODE, GS_FIELD);
GsInitCtx(&gsCtx, WIDTH, HEIGHT, GS_PSMCT32, GS_PSMZ32);
initrender();
AddIntcHandler(2, vsynch, 0);
EnableIntc(2);
GsPutDrawCtx(&gsCtx.draw[0]);
GsPutDispCtx(&gsCtx.disp[1]);
// PCSX2 needs a delay for some reason
{ int i; for(i = 0; i < 1000000; i++); }
clearscreen(0x80, 0x80, 0x80);
// drawtest();
// drawtri();
float angle = 40.0f;
int drawbuf = 0;
int dispbuf = 1;
for(;;){
clearscreen(0x80, 0x80, 0x80);
rw::V3d t = { 0.0f, 0.0f, -4.0f };
camera->getFrame()->translate(&t, rw::COMBINEREPLACE);
rw::V3d axis = { 0.0f, 1.0f, 0.0f };
camera->getFrame()->rotate(&axis, angle, rw::COMBINEPOSTCONCAT);
angle += 1.0f;
camera->beginUpdate();
beginCamera();
FORLIST(lnk, clump->atomics)
drawAtomic(rw::Atomic::fromClump(lnk));
camera->endUpdate();
printf("");
while(vsynchInt == 0);
GsPutDrawCtx(&gsCtx.draw[drawbuf]);
GsPutDispCtx(&gsCtx.disp[dispbuf]);
drawbuf = !drawbuf;
dispbuf = !dispbuf;
vsynchInt = 0;
}
/*
camera->beginUpdate();
beginCamera();
FORLIST(lnk, clump->atomics)
drawAtomic(rw::Atomic::fromClump(lnk));
camera->endUpdate();
printf("hello %p\n", clump);
for(;;)
printf("");
*/
return 0;
}

95
vendor/librw/tools/ps2test/mem.h vendored Normal file
View file

@ -0,0 +1,95 @@
/* FIFOs */
#define VIF0_FIFO (*(volatile uint128*)0x10004000)
#define VIF1_FIFO (*(volatile uint128*)0x10005000)
#define GIF_FIFO (*(volatile uint128*)0x10006000)
#define IPU_out_FIFO (*(volatile uint128*)0x10007000)
#define IPU_in_FIFO (*(volatile uint128*)0x10007010)
/* DMA channels */
// to VIF0
#define D0_CHCR (*(volatile uint32*)0x10008000)
#define D0_MADR (*(volatile uint32*)0x10008010)
#define D0_QWC (*(volatile uint32*)0x10008020)
#define D0_TADR (*(volatile uint32*)0x10008030)
#define D0_ASR0 (*(volatile uint32*)0x10008040)
#define D0_ASR1 (*(volatile uint32*)0x10008050)
// VIF1
#define D1_CHCR (*(volatile uint32*)0x10009000)
#define D1_MADR (*(volatile uint32*)0x10009010)
#define D1_QWC (*(volatile uint32*)0x10009020)
#define D1_TADR (*(volatile uint32*)0x10009030)
#define D1_ASR0 (*(volatile uint32*)0x10009040)
#define D1_ASR1 (*(volatile uint32*)0x10009050)
// to GIF
#define D2_CHCR (*(volatile uint32*)0x1000a000)
#define D2_MADR (*(volatile uint32*)0x1000a010)
#define D2_QWC (*(volatile uint32*)0x1000a020)
#define D2_TADR (*(volatile uint32*)0x1000a030)
#define D2_ASR0 (*(volatile uint32*)0x1000a040)
#define D2_ASR1 (*(volatile uint32*)0x1000a050)
// fromIPU
#define D3_CHCR (*(volatile uint32*)0x1000b000)
#define D3_MADR (*(volatile uint32*)0x1000b010)
#define D3_QWC (*(volatile uint32*)0x1000b020)
// toIPU
#define D4_CHCR (*(volatile uint32*)0x1000b400)
#define D4_MADR (*(volatile uint32*)0x1000b410)
#define D4_QWC (*(volatile uint32*)0x1000b420)
#define D4_TADR (*(volatile uint32*)0x1000b430)
// from SIF0
#define D5_CHCR (*(volatile uint32*)0x1000c000)
#define D5_MADR (*(volatile uint32*)0x1000c010)
#define D5_QWC (*(volatile uint32*)0x1000c020)
// to SIF1
#define D6_CHCR (*(volatile uint32*)0x1000c400)
#define D6_MADR (*(volatile uint32*)0x1000c410)
#define D6_QWC (*(volatile uint32*)0x1000c420)
#define D6_TADR (*(volatile uint32*)0x1000c430)
// SIF2
#define D7_CHCR (*(volatile uint32*)0x1000c800)
#define D7_MADR (*(volatile uint32*)0x1000c810)
#define D7_QWC (*(volatile uint32*)0x1000c820)
// fromSPR
#define D8_CHCR (*(volatile uint32*)0x1000d000)
#define D8_MADR (*(volatile uint32*)0x1000d010)
#define D8_QWC (*(volatile uint32*)0x1000d020)
#define D8_SADR (*(volatile uint32*)0x1000d080)
// toSPR
#define D9_CHCR (*(volatile uint32*)0x1000d400)
#define D9_MADR (*(volatile uint32*)0x1000d410)
#define D9_QWC (*(volatile uint32*)0x1000d420)
#define D9_TADR (*(volatile uint32*)0x1000d430)
#define D9_SADR (*(volatile uint32*)0x1000d480)
/* DMA controller */
#define D_CTRL (*(volatile uint32*)0x1000e000)
#define D_STAT (*(volatile uint32*)0x1000e010)
#define D_PCR (*(volatile uint32*)0x1000e020)
#define D_SQWC (*(volatile uint32*)0x1000e030)
#define D_RBSR (*(volatile uint32*)0x1000e040)
#define D_RBOR (*(volatile uint32*)0x1000e050)
#define D_STADR (*(volatile uint32*)0x1000e060)
#define D_ENABLER (*(volatile uint32*)0x1000f520)
#define D_ENABLEW (*(volatile uint32*)0x1000f590)
/* GS privileged registers */
#define GS_PMODE (*(volatile uint64*)0x12000000)
#define GS_SMODE1 (*(volatile uint64*)0x12000010)
#define GS_SMODE2 (*(volatile uint64*)0x12000020)
#define GS_SRFSH (*(volatile uint64*)0x12000030)
#define GS_SYNCH1 (*(volatile uint64*)0x12000040)
#define GS_SYNCH2 (*(volatile uint64*)0x12000050)
#define GS_SYNCV (*(volatile uint64*)0x12000060)
#define GS_DISPFB1 (*(volatile uint64*)0x12000070)
#define GS_DISPLAY1 (*(volatile uint64*)0x12000080)
#define GS_DISPFB2 (*(volatile uint64*)0x12000090)
#define GS_DISPLAY2 (*(volatile uint64*)0x120000a0)
#define GS_EXTBUF (*(volatile uint64*)0x120000b0)
#define GS_EXTDATA (*(volatile uint64*)0x120000c0)
#define GS_EXTWRITE (*(volatile uint64*)0x120000d0)
#define GS_BGCOLOR (*(volatile uint64*)0x120000e0)
#define GS_CSR (*(volatile uint64*)0x12001000)
#define GS_IMR (*(volatile uint64*)0x12001010)
#define GS_BUSDIR (*(volatile uint64*)0x12001040)
#define GS_SIGLBLID (*(volatile uint64*)0x12001080)

23
vendor/librw/tools/ps2test/ps2.h vendored Normal file
View file

@ -0,0 +1,23 @@
#include <kernel.h>
typedef int quad __attribute__((mode(TI)));
typedef int int128 __attribute__((mode(TI)));
typedef unsigned int uquad __attribute__((mode(TI)));
typedef unsigned int uint128 __attribute__((mode(TI)));
#define MAKE128(RES,MSB,LSB) \
__asm__ ( "pcpyld %0, %1, %2" : "=r" (RES) : "r" ((uint64)MSB), "r" ((uint64)LSB))
#define UINT64(LOW,HIGH) (((uint64)HIGH)<<32 | ((uint64)LOW))
#define MAKEQ(RES,W0,W1,W2,W3) MAKE128(RES,UINT64(W2,W3),UINT64(W0,W1))
#define BIT64(v,s) (((uint64)(v)) << (s))
#include "mem.h"
#include "gs.h"
extern uint128 packetbuf[128];
void waitDMA(volatile uint32 *chcr);
void toGIF(void *src, int n);
void drawcube(void);

View file

@ -0,0 +1,93 @@
.global defaultPipe
.equ vertexTop, 0x3d0
.equ numInAttribs, 4
.equ numOutAttribs, 3
.equ numOutBuf, 2
.equ vertCount, ((vertexTop-numOutBuf)/(numInAttribs*2+numOutAttribs*numOutBuf))
.equ offset, (vertCount*numInAttribs)
.equ outBuf1, (2*offset)
.equ outSize, ((vertexTop-outBuf1-2)/2)
.equ outBuf2, (outBuf1+outSize)
.equ lightMat, 0x3d0
.equ ambientLight, 0x3d4
.equ lightDir, 0x3d5
.equ matrix, 0x3f0
.equ XYZScale, 0x3f7
.equ XYZOffset, 0x3f8
.equ gifTag, 0x3fa
.equ matColor, 0x3fb
.equ surfProps, 0x3fc
.balign 16,0
defaultPipe:
DMAret *
MPG 0, *
.vu
Start:
#include "setup_persp.vu"
Cnt:
NOP XTOP VI02 ; input pointer
NOP LQ VF01, gifTag(VI00)
NOP XITOP VI01 ; vertex count
NOP IADDIU VI05, VI00, 0x4000
NOP IADD VI05, VI05, VI05
NOP IOR VI05, VI05, VI01
NOP SQ VF01, 0(VI12)
NOP ISW.x VI05, 0(VI12)
NOP IADDIU VI03, VI12, 1 ; output pointer
NOP LQ VF18, lightMat(VI00)
NOP LQ VF19, lightMat+1(VI00)
NOP LQ VF20, lightMat+2(VI00)
Loop:
NOP LQI VF01, (VI02++) ; vertex
NOP LQI VF02, (VI02++) ; UV
NOP LQI VF03, (VI02++) ; color
NOP LQI VF04, (VI02++) ; normal
MULAw.xyzw ACC, VF31, VF00w NOP ; transform vertex
MADDAx.xyw ACC, VF28, VF01x NOP
MADDAy.xyw ACC, VF29, VF01y NOP
MADDz.xyzw VF01, VF30, VF01z NOP
ITOF0 VF03, VF03 NOP
ITOF0[I] VF04, VF04 LOI 0.0078125 ; - normal scale
NOP NOP
NOP DIV Q, VF00w, VF01w
NOP WAITQ
MULq VF01, VF01, Q NOP ; perspective division
MULi VF04, VF04, I NOP ; scale normal
NOP MR32.z VF02, VF00
NOP NOP
SUB.w VF01, VF01, VF01 NOP
MULAx.xyz ACC, VF18, VF04x NOP ; transform normal
MADDAy.xyz ACC, VF19, VF04y NOP
MADDz.xyz VF04, VF20, VF04z NOP
ADD.xyz VF01, VF01, VF25 NOP
MULq VF02, VF02, Q NOP
NOP NOP
FTOI0 VF03, VF03 NOP
FTOI4 VF01, VF01 NOP
NOP SQ VF04, -2(VI02) ; store normal
NOP IADDI VI01, VI01, -1
NOP SQI VF02, (VI03++) ; STQ
NOP SQI VF03, (VI03++) ; color
NOP SQI VF01, (VI03++) ; vertex
NOP IBNE VI01, VI00, Loop
NOP NOP
#include "light.vu"
NOP XGKICK VI12
NOP IADD VI15,VI00,VI12
NOP IADD VI12,VI00,VI13
NOP[E] IADD VI13,VI00,VI15
NOP NOP
NOP B Cnt
NOP NOP
.EndMPG
.EndDmaData

94
vendor/librw/tools/ps2test/vu/light.vu vendored Normal file
View file

@ -0,0 +1,94 @@
; Ambient light:
NOP LQ VF26, ambientLight(VI00)
NOP XITOP VI01
NOP IADDIU VI03, VI12, 2
Ambloop:
NOP LQ VF03, 0(VI03) ; output color
NOP NOP
NOP NOP
NOP NOP
ITOF0 VF03, VF03 NOP
NOP NOP
NOP NOP
NOP NOP
ADD.xyz VF03, VF03, VF26 NOP
NOP NOP
NOP NOP
NOP NOP
FTOI0 VF03, VF03 NOP
NOP IADDI VI01, VI01, -1
NOP IADDIU VI03, VI03, numOutAttribs
NOP IBNE VI01, VI00, Ambloop
NOP SQ VF03, -numOutAttribs(VI03)
; end amblight
; Direct Light
NOP LQ VF26, lightDir(VI00)
NOP XITOP VI01
NOP XTOP VI02
NOP IADDIU VI03, VI12, 2
SUB.xyz VF26, VF00, VF26 NOP
Dirloop:
NOP LQ VF01, 3(VI02); ; normal
NOP LQ VF02, 0(VI03); ; output color
NOP NOP
NOP NOP
MUL VF03, VF01, VF26 NOP
ITOF0 VF02, VF02 NOP
NOP NOP
NOP NOP
ADDy.x VF03, VF03, VF03y NOP
NOP NOP
NOP NOP
NOP NOP
ADDz.x VF03, VF03, VF03z NOP
NOP NOP
NOP NOP
NOP NOP
MAX.x VF03, VF00, VF03 NOP ; clamp to 0
NOP[I] LOI 255
NOP NOP
NOP NOP
MULi.x VF03, VF03, I NOP
NOP NOP
NOP NOP
NOP NOP
ADDx.xyz VF02, VF02, VF03x NOP
NOP NOP
NOP NOP
NOP NOP
FTOI0 VF02, VF02 NOP
NOP IADDI VI01, VI01, -1
NOP IADDIU VI02, VI02, numInAttribs
NOP IADDIU VI03, VI03, numOutAttribs
NOP IBNE VI01, VI00, Dirloop
NOP SQ VF02, -numOutAttribs(VI03)
; end dirlight
; Material color and clamp
NOP LQ VF27, matColor(VI00)
NOP XITOP VI01
NOP IADDIU VI03, VI12, 2
Colorloop:
NOP LQ VF03, 0(VI03)
NOP NOP
NOP NOP
NOP NOP
ITOF0 VF03, VF03 NOP
NOP NOP
NOP NOP
NOP NOP
MUL VF03, VF03, VF27 NOP
NOP[I] LOI 255
NOP NOP
NOP NOP
MINIi VF03, VF03, I NOP
NOP NOP
NOP NOP
NOP NOP
FTOI0 VF03, VF03 NOP
NOP IADDI VI01, VI01, -1
NOP IADDIU VI03, VI03, numOutAttribs
NOP IBNE VI01, VI00, Colorloop
NOP SQ VF03, -numOutAttribs(VI03)
; end material color

View file

@ -0,0 +1,39 @@
/* This is the the projection matrix we start with:
* 1/2w 0 ox/2w + 1/2 -ox/2w
* 0 -1/2h -oy/2h + 1/2 oy/2h
* 0 0 1 0
* 0 0 1 0
* To get rid of the +1/2 in the combined matrix we
* subtract the z-row/2 from the x- and y-rows.
*
* The z-row is then set to [0 0 0 1] such that multiplication
* by XYZscale gives [0 0 0 zScale]. After perspective division
* and addition of XYZoffset we then get zScale/w + zShift for z.
*
* XYZScale scales xy to the resolution and z by zScale.
* XYZOffset translates xy to the GS coordinate system (where
* [2048, 2048] is the center of the frame buffer) and add zShift to z.
*/
; constant:
; VF28-VF31 transformation matrix
; VF25 XYZ offset
SUB.z VF28, VF28, VF28 LOI 0.5 ; right.z = 0
SUB.z VF29, VF29, VF29 LQ VF28, matrix(VI00) ; up.z = 0 - load matrix
SUB.z VF30, VF30, VF30 LQ VF29, matrix+1(VI00) ; at.z = 0 - load matrix
ADDw.z VF31, VF00, VF00 LQ VF30, matrix+2(VI00) ; at.z = 1 - load matrix
NOP LQ VF31, matrix+3(VI00) ; - load matrix
MULi.w VF20, VF28, I LQ.xyz VF01, XYZScale(VI00) ; fix matrix - load scale
MULi.w VF21, VF29, I NOP ; fix matrix
MULi.w VF22, VF30, I NOP ; fix matrix
MULi.w VF23, VF31, I NOP ; fix matrix
SUBw.xy VF28, VF28, VF20 NOP ; fix matrix
SUBw.xy VF29, VF29, VF21 NOP ; fix matrix
SUBw.xy VF30, VF30, VF22 NOP ; fix matrix
SUBw.xy VF31, VF31, VF23 NOP ; fix matrix
MUL.xy VF28, VF28, VF01 LQ.xyz VF25, XYZOffset(VI00) ; scale matrix
MUL.xy VF29, VF29, VF01 IADDIU VI12, VI00, outBuf1 ; scale matrix
MUL.xy VF30, VF30, VF01 IADDIU VI13, VI00, outBuf2 ; scale matrix
MUL.xyz VF31, VF31, VF01 NOP ; scale matrix

View file

@ -0,0 +1,94 @@
.global skinPipe
.equ vertexTop, 0x2d0
.equ numInAttribs, 5
.equ numOutAttribs, 3
.equ numOutBuf, 2
.equ vertCount, ((vertexTop-numOutBuf)/(numInAttribs*2+numOutAttribs*numOutBuf))
.equ offset, (vertCount*numInAttribs)
.equ outBuf1, (2*offset)
.equ outSize, ((vertexTop-outBuf1-2)/2)
.equ outBuf2, (outBuf1+outSize)
.equ lightMat, 0x3d0
.equ ambientLight, 0x3d4
.equ lightDir, 0x3d5
.equ matrix, 0x3f0
.equ XYZScale, 0x3f7
.equ XYZOffset, 0x3f8
.equ gifTag, 0x3fa
.equ matColor, 0x3fb
.equ surfProps, 0x3fc
.balign 16,0
skinPipe:
DMAret *
MPG 0, *
.vu
Start:
#include "setup_persp.vu"
Cnt:
NOP XTOP VI02 ; input pointer
NOP LQ VF01, gifTag(VI00)
NOP XITOP VI01 ; vertex count
NOP IADDIU VI05, VI00, 0x4000
NOP IADD VI05, VI05, VI05
NOP IOR VI05, VI05, VI01
NOP SQ VF01, 0(VI12)
NOP ISW.x VI05, 0(VI12)
NOP IADDIU VI03, VI12, 1 ; output pointer
NOP LQ VF18, lightMat(VI00)
NOP LQ VF19, lightMat+1(VI00)
NOP LQ VF20, lightMat+2(VI00)
Loop:
NOP LQI VF01, (VI02++) ; vertex
NOP LQI VF02, (VI02++) ; UV
NOP LQI VF03, (VI02++) ; color
NOP LQI VF04, (VI02++) ; normal
NOP IADDIU VI02, VI02, 1 ; skip weights
MULAw.xyzw ACC, VF31, VF00w NOP ; transform vertex
MADDAx.xyw ACC, VF28, VF01x NOP
MADDAy.xyw ACC, VF29, VF01y NOP
MADDz.xyzw VF01, VF30, VF01z NOP
ITOF0 VF03, VF03 NOP
ITOF0[I] VF04, VF04 LOI 0.0078125 ; - normal scale
NOP NOP
NOP DIV Q, VF00w, VF01w
NOP WAITQ
MULq VF01, VF01, Q NOP ; perspective division
MULi VF04, VF04, I NOP ; scale normal
NOP MR32.z VF02, VF00
NOP NOP
SUB.w VF01, VF01, VF01 NOP
MULAx.xyz ACC, VF18, VF04x NOP ; transform normal
MADDAy.xyz ACC, VF19, VF04y NOP
MADDz.xyz VF04, VF20, VF04z NOP
ADD.xyz VF01, VF01, VF25 NOP
MULq VF02, VF02, Q NOP
NOP NOP
FTOI0 VF03, VF03 NOP
FTOI4 VF01, VF01 NOP
NOP SQ VF04, -2(VI02) ; store normal
NOP IADDI VI01, VI01, -1
NOP SQI VF02, (VI03++) ; STQ
NOP SQI VF03, (VI03++) ; color
NOP SQI VF01, (VI03++) ; vertex
NOP IBNE VI01, VI00, Loop
NOP NOP
#include "light.vu"
NOP XGKICK VI12
NOP IADD VI15,VI00,VI12
NOP IADD VI12,VI00,VI13
NOP[E] IADD VI13,VI00,VI15
NOP NOP
NOP B Cnt
NOP NOP
.EndMPG
.EndDmaData

View file

@ -0,0 +1,16 @@
add_executable(ska2anm
ska2anm.cpp
)
target_link_libraries(ska2anm
PUBLIC
librw::librw
)
librw_platform_target(ska2anm INSTALL)
if(LIBRW_INSTALL)
install(TARGETS ska2anm
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
endif()

83
vendor/librw/tools/ska2anm/ska2anm.cpp vendored Normal file
View file

@ -0,0 +1,83 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <rw.h>
#include <args.h>
using namespace rw;
char *argv0;
void
usage(void)
{
fprintf(stderr, "usage: %s in.ska [out.anm]\n", argv0);
fprintf(stderr, " or: %s in.anm [out.ska]\n", argv0);
exit(1);
}
int
main(int argc, char *argv[])
{
rw::Engine::init();
rw::registerHAnimPlugin();
rw::Engine::open(nil);
rw::Engine::start();
ARGBEGIN{
case 'v':
sscanf(EARGF(usage()), "%x", &rw::version);
break;
default:
usage();
}ARGEND;
if(argc < 1)
usage();
StreamFile stream;
if(!stream.open(argv[0], "rb")){
fprintf(stderr, "Error: couldn't open %s\n", argv[0]);
return 1;
}
int32 firstword = stream.readU32();
stream.seek(0, 0);
Animation *anim = nil;
if(firstword == ID_ANIMANIMATION){
// it's an anm file
if(findChunk(&stream, ID_ANIMANIMATION, nil, nil))
anim = Animation::streamRead(&stream);
}else{
// it's a ska file
anim = Animation::streamReadLegacy(&stream);
}
stream.close();
if(anim == nil){
fprintf(stderr, "Error: couldn't read anim file\n");
return 1;
}
const char *file;
if(argc > 1)
file = argv[1];
else if(firstword == ID_ANIMANIMATION)
file = "out.ska";
else
file = "out.anm";
if(!stream.open(file, "wb")){
fprintf(stderr, "Error: couldn't open %s\n", file);
return 1;
}
if(firstword == ID_ANIMANIMATION)
anim->streamWriteLegacy(&stream);
else
anim->streamWrite(&stream);
anim->destroy();
return 0;
}

View file

@ -0,0 +1,19 @@
add_executable(subrast WIN32
main.cpp
subrast.cpp
subrast.h
)
target_link_libraries(subrast
PUBLIC
librw::skeleton
librw::librw
)
add_custom_command(
TARGET subrast POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:subrast>/files"
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/files" "$<TARGET_FILE_DIR:subrast>/files"
)
librw_platform_target(subrast)

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

354
vendor/librw/tools/subrast/main.cpp vendored Normal file
View file

@ -0,0 +1,354 @@
#include <rw.h>
#include <skeleton.h>
#include <assert.h>
#include "subrast.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 BorderColor = { 128, 128, 128, 0 };
rw::Clump *Clump = nil;
rw::Light *MainLight = nil;
rw::Light *AmbientLight = nil;
rw::World *World;
rw::Charset *Charset;
const char *SubCameraCaption[4] = {
"Perspective view",
"Parallel view: Z-axis",
"Parallel view: X-axis",
"Parallel view: Y-axis"
};
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 };
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);
}
rw::Light*
CreateAmbientLight(rw::World *world)
{
rw::Light *light = rw::Light::create(rw::Light::AMBIENT);
assert(light);
World->addLight(light);
return light;
}
rw::Light*
CreateMainLight(rw::World *world)
{
rw::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);
return light;
}
rw::Clump*
CreateClump(rw::World *world)
{
rw::Clump *clump;
rw::StreamFile in;
rw::Image::setSearchPath("files/textures/");
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();
frame->rotate(&Xaxis, -120.0f, rw::COMBINEREPLACE);
frame->rotate(&Yaxis, 45.0f, rw::COMBINEPOSTCONCAT);
World->addClump(clump);
return clump;
}
void
RotateClump(float xAngle, float yAngle)
{
rw::Matrix *cameraMatrix = &Camera->getFrame()->matrix;
rw::Frame *frame = Clump->getFrame();
rw::V3d pos = frame->matrix.pos;
pos = rw::scale(pos, -1.0f);
frame->translate(&pos, rw::COMBINEPOSTCONCAT);
frame->rotate(&cameraMatrix->up, xAngle, rw::COMBINEPOSTCONCAT);
frame->rotate(&cameraMatrix->right, yAngle, rw::COMBINEPOSTCONCAT);
pos = rw::scale(pos, -1.0f);
frame->translate(&pos, rw::COMBINEPOSTCONCAT);
}
void
Initialize(void)
{
sk::globals.windowtitle = "Sub-raster 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();
AmbientLight = CreateAmbientLight(World);
MainLight = CreateMainLight(World);
Clump = CreateClump(World);
if (Clump == nil)
return false;
CreateCameras(World);
UpdateSubRasters(Camera, sk::globals.width, sk::globals.height);
rw::SetRenderState(rw::CULLMODE, rw::CULLBACK);
rw::SetRenderState(rw::ZTESTENABLE, 1);
rw::SetRenderState(rw::ZWRITEENABLE, 1);
ImGui_ImplRW_Init();
ImGui::StyleColorsClassic();
return true;
}
void
Terminate3D(void)
{
DestroyCameras(World);
if(AmbientLight){
World->removeLight(AmbientLight);
AmbientLight->destroy();
AmbientLight = nil;
}
if(MainLight){
World->removeLight(MainLight);
rw::Frame *frame = MainLight->getFrame();
MainLight->setFrame(nil);
frame->destroy();
MainLight->destroy();
MainLight = nil;
}
if(Clump){
World->removeClump(Clump);
Clump->destroy();
Clump = nil;
}
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)
{
for(int i = 0; i < 4; i++){
rw::Raster *scr = SubCameras[i]->frameBuffer;
rw::int32 scrw = scr->width;
rw::int32 scrh = scr->height;
rw::int32 captionWidth = strlen(SubCameraCaption[i])*Charset->desc.width;
if(captionWidth < scrw && scrh > Charset->desc.height*2){
rw::int32 x = scr->offsetX + (scrw - captionWidth)/2;
rw::int32 y = scr->offsetY + Charset->desc.height;
Charset->print(SubCameraCaption[i], x, y, 0);
}
}
}
rw::RGBA BackgroundColors[] = {
{ 64, 64, 64, 0 },
{ 128, 0, 0, 0 },
{ 0, 128, 0, 0 },
{ 0, 0, 128, 0 },
};
void
Render(float timeDelta)
{
Camera->clear(&BorderColor, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
for(int i = 0; i < 4; i++){
SubCameras[i]->clear(&BackgroundColor, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
// SubCameras[i]->clear(&BackgroundColors[i], rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
SubCameras[i]->beginUpdate();
World->render();
SubCameras[i]->endUpdate();
}
Camera->beginUpdate();
DisplayOnScreenInfo();
Camera->endUpdate();
Camera->showRaster(0);
}
void
Idle(float timeDelta)
{
Render(timeDelta);
}
int MouseX, MouseY;
int MouseDeltaX, MouseDeltaY;
int MouseButtons;
bool Rotating;
void
KeyUp(int key)
{
}
void
KeyDown(int key)
{
switch(key){
case sk::KEY_ESC:
sk::globals.quit = 1;
break;
}
}
void
MouseBtn(sk::MouseState *mouse)
{
MouseButtons = mouse->buttons;
Rotating = !!(MouseButtons&1);
}
void
MouseMove(sk::MouseState *mouse)
{
MouseDeltaX = mouse->posx - MouseX;
MouseDeltaY = mouse->posy - MouseY;
MouseX = mouse->posx;
MouseY = mouse->posy;
if(Rotating)
RotateClump(-MouseDeltaX, MouseDeltaY);
}
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;
if(::Camera){
sk::CameraSize(::Camera, r);
::Camera->setFOV(FOV, (float)sk::globals.width/sk::globals.height);
UpdateSubRasters(::Camera, r->w, r->h);
}
break;
case IDLE:
Idle(*(float*)param);
return EVENTPROCESSED;
}
return sk::EVENTNOTPROCESSED;
}

141
vendor/librw/tools/subrast/subrast.cpp vendored Normal file
View file

@ -0,0 +1,141 @@
#include <rw.h>
#include <skeleton.h>
#include "subrast.h"
rw::Camera *Camera;
rw::Camera *SubCameras[4];
void
CameraSetViewWindow(rw::Camera *camera, float width, float height, float vw)
{
rw::V2d viewWindow;
// TODO: aspect ratio when fullscreen
if(width > height){
viewWindow.x = vw;
viewWindow.y = vw / (width/height);
}else{
viewWindow.x = vw / (height/width);
viewWindow.y = vw;
}
camera->setViewWindow(&viewWindow);
}
void
UpdateSubRasters(rw::Camera *mainCamera, rw::int32 mainWidth, rw::int32 mainHeight)
{
rw::Rect rect[4];
float width, height, border;
border = mainHeight*0.05f;
width = (mainWidth - border*3.0f) / 2.0f;
height = (mainHeight - border*3.0f) / 2.0f;
// top left
rect[0].x = border;
rect[0].y = border;
rect[0].w = width;
rect[0].h = height;
// top right
rect[1].x = border*2 + width;
rect[1].y = border;
rect[1].w = width;
rect[1].h = height;
// bottom left
rect[2].x = border;
rect[2].y = border*2 + height;
rect[2].w = width;
rect[2].h = height;
// bottom left
rect[3].x = border*2 + width;
rect[3].y = border*2 + height;
rect[3].w = width;
rect[3].h = height;
CameraSetViewWindow(SubCameras[0], width, height, 0.5f);
for(int i = 1; i < 4; i++)
CameraSetViewWindow(SubCameras[i], width, height, 0.5f + 0.4f);
for(int i = 0; i < 4; i++){
SubCameras[i]->frameBuffer->subRaster(mainCamera->frameBuffer, &rect[i]);
SubCameras[i]->zBuffer->subRaster(mainCamera->zBuffer, &rect[i]);
}
}
void
PositionSubCameras(void)
{
rw::Frame *frame;
rw::V3d pos;
const float dist = 2.5f;
// perspective
pos.x = pos.y = 0.0f;
pos.z = -4.0f;
frame = SubCameras[0]->getFrame();
frame->translate(&pos, rw::COMBINEREPLACE);
// look along z
pos.x = pos.y = 0.0f;
pos.z = -dist;
frame = SubCameras[1]->getFrame();
frame->translate(&pos, rw::COMBINEREPLACE);
// look along x
pos.x = -dist;
pos.y = pos.z = 0.0f;
frame = SubCameras[2]->getFrame();
frame->rotate(&Yaxis, 90.0f, rw::COMBINEREPLACE);
frame->translate(&pos, rw::COMBINEPOSTCONCAT);
// look along y
pos.x = pos.z = 0.0f;
pos.y = -dist;
frame = SubCameras[3]->getFrame();
frame->rotate(&Xaxis, -90.0f, rw::COMBINEREPLACE);
frame->translate(&pos, rw::COMBINEPOSTCONCAT);
}
void
CreateCameras(rw::World *world)
{
Camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
assert(Camera);
for(int i = 0; i < 4; i++){
SubCameras[i] = sk::CameraCreate(0, 0, 1);
assert(SubCameras[i]);
SubCameras[i]->setNearPlane(0.1f);
SubCameras[i]->setFarPlane(30.0f);
world->addCamera(SubCameras[i]);
if(i > 0)
SubCameras[i]->setProjection(rw::Camera::PARALLEL);
}
PositionSubCameras();
}
void
DestroyCameras(rw::World *world)
{
if(Camera){
sk::CameraDestroy(Camera);
Camera = nil;
}
for(int i = 0; i < 4; i++)
if(SubCameras[i]){
world->removeCamera(SubCameras[i]);
sk::CameraDestroy(SubCameras[i]);
SubCameras[i] = nil;
}
}

10
vendor/librw/tools/subrast/subrast.h vendored Normal file
View file

@ -0,0 +1,10 @@
extern rw::Camera *Camera;
extern rw::Camera *SubCameras[4];
void CreateCameras(rw::World *world);
void DestroyCameras(rw::World *world);
void UpdateSubRasters(rw::Camera *mainCamera, rw::int32 mainWidth, rw::int32 mainHeight);
extern rw::V3d Xaxis;
extern rw::V3d Yaxis;
extern rw::V3d Zaxis;