mirror of
https://github.com/aap/librw.git
synced 2025-12-30 22:39:59 +00:00
hopalong orbit viewer; also bezier patches in playground
This commit is contained in:
448
tools/hopalong/main.cpp
Normal file
448
tools/hopalong/main.cpp
Normal file
@@ -0,0 +1,448 @@
|
||||
#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;
|
||||
|
||||
rw::Texture *ParticleTex;
|
||||
rw::Raster *ParticleRaster;
|
||||
|
||||
static rw::RWDEVICE::Im2DVertex im2dVerts[1024];
|
||||
static int numImVerts;
|
||||
static rw::uint16 imIndices[1024*2];
|
||||
static int numImIndices;
|
||||
static rw::PrimitiveType imPrim;
|
||||
|
||||
void
|
||||
BeginIm2D(rw::PrimitiveType prim)
|
||||
{
|
||||
numImVerts = 0;
|
||||
numImIndices = 0;
|
||||
imPrim = prim;
|
||||
}
|
||||
|
||||
void
|
||||
EndIm2D(void)
|
||||
{
|
||||
rw::im2d::RenderIndexedPrimitive(imPrim, &im2dVerts, numImVerts, &imIndices, numImIndices);
|
||||
}
|
||||
|
||||
void
|
||||
RenderParticle(float x, float y, float sz, rw::RGBA col)
|
||||
{
|
||||
using namespace rw;
|
||||
using namespace RWDEVICE;
|
||||
|
||||
if(numImVerts+4 > nelem(im2dVerts) ||
|
||||
numImIndices+6 > nelem(imIndices)){
|
||||
EndIm2D();
|
||||
numImVerts = 0;
|
||||
numImIndices = 0;
|
||||
}
|
||||
|
||||
float recipZ = 1.0f/Scene.camera->nearPlane;
|
||||
rw::RWDEVICE::Im2DVertex *verts = &im2dVerts[numImVerts];
|
||||
|
||||
x += sk::globals.width/2;
|
||||
y += sk::globals.height/2;
|
||||
|
||||
verts[0].setScreenX(x-sz);
|
||||
verts[0].setScreenY(y-sz);
|
||||
verts[0].setScreenZ(rw::im2d::GetNearZ());
|
||||
verts[0].setCameraZ(Scene.camera->nearPlane);
|
||||
verts[0].setRecipCameraZ(recipZ);
|
||||
verts[0].setColor(col.red, col.green, col.blue, col.alpha);
|
||||
verts[0].setU(0.0f, recipZ);
|
||||
verts[0].setV(0.0f, recipZ);
|
||||
|
||||
verts[1].setScreenX(x+sz);
|
||||
verts[1].setScreenY(y-sz);
|
||||
verts[1].setScreenZ(rw::im2d::GetNearZ());
|
||||
verts[1].setCameraZ(Scene.camera->nearPlane);
|
||||
verts[1].setRecipCameraZ(recipZ);
|
||||
verts[1].setColor(col.red, col.green, col.blue, col.alpha);
|
||||
verts[1].setU(1.0f, recipZ);
|
||||
verts[1].setV(0.0f, recipZ);
|
||||
|
||||
verts[2].setScreenX(x+sz);
|
||||
verts[2].setScreenY(y+sz);
|
||||
verts[2].setScreenZ(rw::im2d::GetNearZ());
|
||||
verts[2].setCameraZ(Scene.camera->nearPlane);
|
||||
verts[2].setRecipCameraZ(recipZ);
|
||||
verts[2].setColor(col.red, col.green, col.blue, col.alpha);
|
||||
verts[2].setU(1.0f, recipZ);
|
||||
verts[2].setV(1.0f, recipZ);
|
||||
|
||||
verts[3].setScreenX(x-sz);
|
||||
verts[3].setScreenY(y+sz);
|
||||
verts[3].setScreenZ(rw::im2d::GetNearZ());
|
||||
verts[3].setCameraZ(Scene.camera->nearPlane);
|
||||
verts[3].setRecipCameraZ(recipZ);
|
||||
verts[3].setColor(col.red, col.green, col.blue, col.alpha);
|
||||
verts[3].setU(0.0f, recipZ);
|
||||
verts[3].setV(1.0f, recipZ);
|
||||
|
||||
imIndices[numImIndices+0] = numImVerts+0;
|
||||
imIndices[numImIndices+1] = numImVerts+1;
|
||||
imIndices[numImIndices+2] = numImVerts+2;
|
||||
imIndices[numImIndices+3] = numImVerts+0;
|
||||
imIndices[numImIndices+4] = numImVerts+2;
|
||||
imIndices[numImIndices+5] = numImVerts+3;
|
||||
|
||||
numImVerts += 4;
|
||||
numImIndices += 6;
|
||||
}
|
||||
|
||||
float sgn(float f) { return f < 0.0f ? -1.0f : f > 0.0f ? 1.0f : 0.0f; }
|
||||
|
||||
struct Orbit
|
||||
{
|
||||
ImVec4 color;
|
||||
float StartX;
|
||||
float StartY;
|
||||
float PointSz;
|
||||
int numIterations;
|
||||
bool used;
|
||||
};
|
||||
|
||||
Orbit orbits[100];
|
||||
int curOrbit = 0;
|
||||
|
||||
float A = 0.0f;
|
||||
float B = 0.0f;
|
||||
float C = 0.0f;
|
||||
float Scale = 50.0f;
|
||||
bool textured = true;
|
||||
bool animateX;
|
||||
bool animateY;
|
||||
bool animateA;
|
||||
bool animateB;
|
||||
bool animateC;
|
||||
|
||||
void
|
||||
ResetOrbit(Orbit *o)
|
||||
{
|
||||
o->color = ImVec4(1.0f, 0.0f, 0.0f, 1.00f);
|
||||
o->StartX = 1.0f;
|
||||
o->StartY = 0.0f;
|
||||
o->PointSz = 3.0f;
|
||||
o->numIterations = 1000;
|
||||
o->used = false;
|
||||
}
|
||||
|
||||
void
|
||||
RenderOrbit(Orbit *o)
|
||||
{
|
||||
rw::RGBA red = { 0xFF, 0, 0, 0xFF };
|
||||
rw::RGBA color = rw::makeRGBA(o->color.x*255, o->color.y*255, o->color.z*255, o->color.w*255);
|
||||
|
||||
float x1, y1;
|
||||
float x0 = o->StartX;
|
||||
float y0 = o->StartY;
|
||||
int n = o->numIterations;
|
||||
|
||||
if(textured){
|
||||
rw::SetRenderStatePtr(rw::TEXTURERASTER, ParticleRaster);
|
||||
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::LINEAR);
|
||||
}else
|
||||
rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
|
||||
BeginIm2D(rw::PRIMTYPETRILIST);
|
||||
while(n--){
|
||||
x1 = y0 - sgn(x0)*sqrtf(fabs(B*x0 - C));
|
||||
// x1 = y0 - sgn(x0)*logf(fabs(B*x0 - C));
|
||||
y1 = A - x0;
|
||||
RenderParticle(x1*Scale, y1*Scale, o->PointSz, color);
|
||||
x0 = x1;
|
||||
y0 = y1;
|
||||
}
|
||||
EndIm2D();
|
||||
}
|
||||
|
||||
void
|
||||
RenderHopalong(void)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < nelem(orbits); i++)
|
||||
if(orbits[i].used)
|
||||
RenderOrbit(&orbits[i]);
|
||||
}
|
||||
|
||||
void
|
||||
Init(void)
|
||||
{
|
||||
sk::globals.windowtitle = "Hopalong map";
|
||||
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;
|
||||
}
|
||||
|
||||
#include "particle.inc"
|
||||
|
||||
#include "vfs.h"
|
||||
VFS_file files[] = {
|
||||
{ "particle.png", particle_png, particle_png_len }
|
||||
};
|
||||
VFS vfs = {
|
||||
files, nelem(files)
|
||||
};
|
||||
|
||||
bool
|
||||
InitRW(void)
|
||||
{
|
||||
if(!sk::InitRW())
|
||||
return false;
|
||||
installVFS(&vfs);
|
||||
|
||||
Scene.world = rw::World::create();
|
||||
|
||||
ParticleTex = rw::Texture::read("particle", nil);
|
||||
if(ParticleTex)
|
||||
ParticleRaster = ParticleTex->raster;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
for(int i = 0; i < nelem(orbits); i++)
|
||||
ResetOrbit(&orbits[i]);
|
||||
orbits[0].used = true;
|
||||
|
||||
ImGui_ImplRW_Init();
|
||||
ImGui::StyleColorsClassic();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
orbitGUI(Orbit *o)
|
||||
{
|
||||
ImGui::SliderFloat("x0", &o->StartX, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("y0", &o->StartY, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("Point Size", &o->PointSz, 0.5f, 10.0f);
|
||||
ImGui::SliderInt("NumPoints", &o->numIterations, 1, 10000);
|
||||
ImGui::ColorEdit3("color", (float*)&o->color);
|
||||
|
||||
/*
|
||||
ImGui::Checkbox("Textured", &textured);
|
||||
ImGui::Checkbox("AnimateX", &animateX);
|
||||
ImGui::Checkbox("AnimateY", &animateY);
|
||||
ImGui::Checkbox("AnimateA", &animateA);
|
||||
ImGui::Checkbox("AnimateB", &animateB);
|
||||
ImGui::Checkbox("AnimateC", &animateC);
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
hopalongGUI(void)
|
||||
{
|
||||
int i;
|
||||
static char tmp[128];
|
||||
if(curOrbit >= 0)
|
||||
orbitGUI(&orbits[curOrbit]);
|
||||
ImGui::SliderFloat("A", &A, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("B", &B, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("C", &C, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("Scale", &Scale, 1.0f, 100.0f);
|
||||
for(i = 0; i < nelem(orbits); i++){
|
||||
if(orbits[i].used){
|
||||
sprintf(tmp, "Orbit %d\n", i);
|
||||
if(ImGui::Button(tmp))
|
||||
curOrbit = i;
|
||||
}
|
||||
}
|
||||
if( ImGui::Button("Add Orbit"))
|
||||
for(i = 0; i < nelem(orbits); i++)
|
||||
if(!orbits[i].used){
|
||||
ResetOrbit(&orbits[i]);
|
||||
orbits[i].used = true;
|
||||
curOrbit = i;
|
||||
break;
|
||||
}
|
||||
if(curOrbit >= 0 && ImGui::Button("Remove Orbit")){
|
||||
orbits[curOrbit].used = false;
|
||||
curOrbit = -1;
|
||||
for(i = 0; i < nelem(orbits); i++)
|
||||
if(orbits[i].used){
|
||||
curOrbit = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
Draw(float timeDelta)
|
||||
{
|
||||
static bool show_demo_window = false;
|
||||
|
||||
rw::RGBA clearcol = { 0, 0, 0, 255 };
|
||||
Scene.camera->clear(&clearcol, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ);
|
||||
Scene.camera->beginUpdate();
|
||||
|
||||
ImGui_ImplRW_NewFrame(timeDelta);
|
||||
|
||||
RenderHopalong();
|
||||
|
||||
/*
|
||||
if(animateX) StartX += timeDelta/10000.0f;
|
||||
if(animateY) StartY += timeDelta/10000.0f;
|
||||
if(animateA) A += timeDelta/10000.0f;
|
||||
if(animateB) B += timeDelta/10000.0f;
|
||||
if(animateC) C += timeDelta/10000.0f;
|
||||
*/
|
||||
|
||||
hopalongGUI();
|
||||
|
||||
if(show_demo_window){
|
||||
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver);
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
|
||||
ImGui_ImplRW_RenderDrawLists(ImGui::GetDrawData());
|
||||
|
||||
Scene.camera->endUpdate();
|
||||
Scene.camera->showRaster(0);
|
||||
|
||||
#ifdef __unix__
|
||||
usleep(10000);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyUp(int key)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
KeyDown(int key)
|
||||
{
|
||||
switch(key){
|
||||
case sk::KEY_ESC:
|
||||
sk::globals.quit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int MouseX, MouseY;
|
||||
int MouseDeltaX, MouseDeltaY;
|
||||
int MouseButtons;
|
||||
|
||||
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;
|
||||
if(MouseButtons&1){
|
||||
int mx = MouseX - sk::globals.width/2;
|
||||
int my = MouseY - sk::globals.height/2;
|
||||
if(curOrbit >= 0){
|
||||
orbits[curOrbit].StartX = mx/Scale;
|
||||
orbits[curOrbit].StartY = my/Scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
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:
|
||||
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;
|
||||
// TODO: set aspect ratio
|
||||
if(Scene.camera)
|
||||
sk::CameraSize(Scene.camera, r);
|
||||
break;
|
||||
case IDLE:
|
||||
Draw(*(float*)param);
|
||||
return EVENTPROCESSED;
|
||||
}
|
||||
return sk::EVENTNOTPROCESSED;
|
||||
}
|
||||
Reference in New Issue
Block a user