From 847962910f0bff071f3bf07c9abb87764fb6cac3 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Mon, 13 Jul 2026 12:40:03 +0000 Subject: Import aap/librw @ master Snapshot for re3/reVC vendoring, per @lzcnt. Source: https://github.com/aap/librw (master). --- tools/subrast/CMakeLists.txt | 19 ++ tools/subrast/files/clump.dff | Bin 0 -> 76384 bytes tools/subrast/files/textures/whiteash.png | Bin 0 -> 4313 bytes tools/subrast/main.cpp | 354 ++++++++++++++++++++++++++++++ tools/subrast/subrast.cpp | 141 ++++++++++++ tools/subrast/subrast.h | 10 + 6 files changed, 524 insertions(+) create mode 100644 tools/subrast/CMakeLists.txt create mode 100644 tools/subrast/files/clump.dff create mode 100644 tools/subrast/files/textures/whiteash.png create mode 100644 tools/subrast/main.cpp create mode 100644 tools/subrast/subrast.cpp create mode 100644 tools/subrast/subrast.h (limited to 'tools/subrast') diff --git a/tools/subrast/CMakeLists.txt b/tools/subrast/CMakeLists.txt new file mode 100644 index 0000000..6393734 --- /dev/null +++ b/tools/subrast/CMakeLists.txt @@ -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 "$/files" + COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/files" "$/files" +) + +librw_platform_target(subrast) diff --git a/tools/subrast/files/clump.dff b/tools/subrast/files/clump.dff new file mode 100644 index 0000000..b65e41d Binary files /dev/null and b/tools/subrast/files/clump.dff differ diff --git a/tools/subrast/files/textures/whiteash.png b/tools/subrast/files/textures/whiteash.png new file mode 100644 index 0000000..aa60569 Binary files /dev/null and b/tools/subrast/files/textures/whiteash.png differ diff --git a/tools/subrast/main.cpp b/tools/subrast/main.cpp new file mode 100644 index 0000000..5dbde8a --- /dev/null +++ b/tools/subrast/main.cpp @@ -0,0 +1,354 @@ +#include +#include +#include + +#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; +} diff --git a/tools/subrast/subrast.cpp b/tools/subrast/subrast.cpp new file mode 100644 index 0000000..f91298f --- /dev/null +++ b/tools/subrast/subrast.cpp @@ -0,0 +1,141 @@ +#include +#include + +#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; + } +} diff --git a/tools/subrast/subrast.h b/tools/subrast/subrast.h new file mode 100644 index 0000000..b7c8537 --- /dev/null +++ b/tools/subrast/subrast.h @@ -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; -- cgit v1.2.3