mirror of https://github.com/aap/librw.git
implemented generic lighting callback
This commit is contained in:
parent
a7de23b47e
commit
f47bd33a6a
|
@ -204,7 +204,14 @@ project "imguitest"
|
||||||
kind "WindowedApp"
|
kind "WindowedApp"
|
||||||
characterset ("MBCS")
|
characterset ("MBCS")
|
||||||
skeltool("imguitest")
|
skeltool("imguitest")
|
||||||
files { "tools/imguitest/imgui/*.cpp" }
|
flags { "WinMain" }
|
||||||
|
removeplatforms { "*null" }
|
||||||
|
removeplatforms { "ps2" }
|
||||||
|
|
||||||
|
project "lights"
|
||||||
|
kind "WindowedApp"
|
||||||
|
characterset ("MBCS")
|
||||||
|
skeltool("lights")
|
||||||
flags { "WinMain" }
|
flags { "WinMain" }
|
||||||
removeplatforms { "*null" }
|
removeplatforms { "*null" }
|
||||||
removeplatforms { "ps2" }
|
removeplatforms { "ps2" }
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
//#include <cstdlib>
|
|
||||||
//#include <cstring>
|
|
||||||
//#include <cassert>
|
|
||||||
|
|
||||||
#include "rwbase.h"
|
#include "rwbase.h"
|
||||||
#include "rwerror.h"
|
#include "rwerror.h"
|
||||||
|
|
|
@ -27,7 +27,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
|
||||||
{
|
{
|
||||||
RawMatrix world;
|
RawMatrix world;
|
||||||
|
|
||||||
d3d::lightingCB(!!(atomic->geometry->flags & Geometry::NORMALS));
|
d3d::lightingCB(atomic);
|
||||||
|
|
||||||
Geometry *geo = atomic->geometry;
|
Geometry *geo = atomic->geometry;
|
||||||
d3d::setRenderState(D3DRS_LIGHTING, !!(geo->flags & rw::Geometry::LIGHT));
|
d3d::setRenderState(D3DRS_LIGHTING, !!(geo->flags & rw::Geometry::LIGHT));
|
||||||
|
|
|
@ -66,7 +66,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
|
||||||
|
|
||||||
int lighting = !!(geo->flags & rw::Geometry::LIGHT);
|
int lighting = !!(geo->flags & rw::Geometry::LIGHT);
|
||||||
if(lighting)
|
if(lighting)
|
||||||
d3d::lightingCB(!!(atomic->geometry->flags & Geometry::NORMALS));
|
d3d::lightingCB(atomic);
|
||||||
|
|
||||||
d3d::setRenderState(D3DRS_LIGHTING, lighting);
|
d3d::setRenderState(D3DRS_LIGHTING, lighting);
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,19 @@ IDirect3DDevice9 *d3ddevice = nil;
|
||||||
#define MAX_LIGHTS 8
|
#define MAX_LIGHTS 8
|
||||||
|
|
||||||
void
|
void
|
||||||
lightingCB(bool32 normals)
|
lightingCB(Atomic *atomic)
|
||||||
{
|
{
|
||||||
World *world;
|
WorldLights lightData;
|
||||||
RGBAf ambLight = { 0.0, 0.0, 0.0, 1.0 };
|
Light *directionals[8];
|
||||||
|
Light *locals[8];
|
||||||
|
lightData.directionals = directionals;
|
||||||
|
lightData.numDirectionals = 8;
|
||||||
|
lightData.locals = locals;
|
||||||
|
lightData.numLocals = 8;
|
||||||
|
|
||||||
|
((World*)engine->currentWorld)->enumerateLights(atomic, &lightData);
|
||||||
|
|
||||||
|
int i, n;
|
||||||
RGBA amb;
|
RGBA amb;
|
||||||
D3DLIGHT9 light;
|
D3DLIGHT9 light;
|
||||||
light.Type = D3DLIGHT_DIRECTIONAL;
|
light.Type = D3DLIGHT_DIRECTIONAL;
|
||||||
|
@ -39,34 +48,83 @@ lightingCB(bool32 normals)
|
||||||
light.Attenuation2 = 0.0f;
|
light.Attenuation2 = 0.0f;
|
||||||
light.Theta = 0.0f;
|
light.Theta = 0.0f;
|
||||||
light.Phi = 0.0f;
|
light.Phi = 0.0f;
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
world = (World*)engine->currentWorld;
|
convColor(&amb, &lightData.ambient);
|
||||||
// only unpositioned lights right now
|
d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA(amb.red, amb.green, amb.blue, amb.alpha));
|
||||||
FORLIST(lnk, world->directionalLights){
|
|
||||||
Light *l = Light::fromWorld(lnk);
|
n = 0;
|
||||||
if((l->getFlags() & Light::LIGHTATOMICS) == 0)
|
for(i = 0; i < lightData.numDirectionals; i++){
|
||||||
continue;
|
|
||||||
if(normals &&
|
|
||||||
l->getType() == Light::DIRECTIONAL &&
|
|
||||||
l->getFlags() & Light::LIGHTATOMICS){
|
|
||||||
if(n >= MAX_LIGHTS)
|
if(n >= MAX_LIGHTS)
|
||||||
continue;
|
return;
|
||||||
|
Light *l = lightData.directionals[i];
|
||||||
|
light.Type = D3DLIGHT_DIRECTIONAL;
|
||||||
light.Diffuse = *(D3DCOLORVALUE*)&l->color;
|
light.Diffuse = *(D3DCOLORVALUE*)&l->color;
|
||||||
light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at;
|
light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at;
|
||||||
d3ddevice->SetLight(n, &light);
|
d3ddevice->SetLight(n, &light);
|
||||||
d3ddevice->LightEnable(n, TRUE);
|
d3ddevice->LightEnable(n, TRUE);
|
||||||
n++;
|
n++;
|
||||||
}else if(l->getType() == Light::AMBIENT){
|
}
|
||||||
ambLight.red += l->color.red;
|
|
||||||
ambLight.green += l->color.green;
|
for(i = 0; i < lightData.numLocals; i++){
|
||||||
ambLight.blue += l->color.blue;
|
if(n >= MAX_LIGHTS)
|
||||||
|
return;
|
||||||
|
Light *l = lightData.locals[i];
|
||||||
|
switch(l->getType()){
|
||||||
|
case Light::POINT:
|
||||||
|
light.Type = D3DLIGHT_POINT;
|
||||||
|
light.Diffuse = *(D3DCOLORVALUE*)&l->color;
|
||||||
|
light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos;
|
||||||
|
light.Direction.x = 0.0f;
|
||||||
|
light.Direction.y = 0.0f;
|
||||||
|
light.Direction.z = 0.0f;
|
||||||
|
light.Range = l->radius;
|
||||||
|
light.Falloff = 1.0f;
|
||||||
|
light.Attenuation0 = 1.0f;
|
||||||
|
light.Attenuation1 = 0.0f/l->radius;
|
||||||
|
light.Attenuation2 = 5.0f/(l->radius*l->radius);
|
||||||
|
d3ddevice->SetLight(n, &light);
|
||||||
|
d3ddevice->LightEnable(n, TRUE);
|
||||||
|
n++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Light::SPOT:
|
||||||
|
light.Type = D3DLIGHT_SPOT;
|
||||||
|
light.Diffuse = *(D3DCOLORVALUE*)&l->color;
|
||||||
|
light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos;
|
||||||
|
light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at;
|
||||||
|
light.Range = l->radius;
|
||||||
|
light.Falloff = 1.0f;
|
||||||
|
light.Attenuation0 = 1.0f;
|
||||||
|
light.Attenuation1 = 0.0f/l->radius;
|
||||||
|
light.Attenuation2 = 5.0f/(l->radius*l->radius);
|
||||||
|
light.Theta = l->getAngle()*2.0f;
|
||||||
|
light.Phi = light.Theta;
|
||||||
|
d3ddevice->SetLight(n, &light);
|
||||||
|
d3ddevice->LightEnable(n, TRUE);
|
||||||
|
n++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Light::SOFTSPOT:
|
||||||
|
light.Type = D3DLIGHT_SPOT;
|
||||||
|
light.Diffuse = *(D3DCOLORVALUE*)&l->color;
|
||||||
|
light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos;
|
||||||
|
light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at;
|
||||||
|
light.Range = l->radius;
|
||||||
|
light.Falloff = 1.0f;
|
||||||
|
light.Attenuation0 = 1.0f;
|
||||||
|
light.Attenuation1 = 0.0f/l->radius;
|
||||||
|
light.Attenuation2 = 5.0f/(l->radius*l->radius);
|
||||||
|
light.Theta = 0.0f;
|
||||||
|
light.Phi = l->getAngle()*2.0f;
|
||||||
|
d3ddevice->SetLight(n, &light);
|
||||||
|
d3ddevice->LightEnable(n, TRUE);
|
||||||
|
n++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(; n < MAX_LIGHTS; n++)
|
for(; n < MAX_LIGHTS; n++)
|
||||||
d3ddevice->LightEnable(n, FALSE);
|
d3ddevice->LightEnable(n, FALSE);
|
||||||
convColor(&amb, &ambLight);
|
|
||||||
d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA(amb.red, amb.green, amb.blue, amb.alpha));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,7 +37,7 @@ extern IDirect3DDevice9 *d3ddevice;
|
||||||
void setD3dMaterial(D3DMATERIAL9 *mat9);
|
void setD3dMaterial(D3DMATERIAL9 *mat9);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void lightingCB(bool32 normals);
|
void lightingCB(Atomic *atomic);
|
||||||
|
|
||||||
#define COLOR_ARGB(a, r, g, b) ((rw::uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
|
#define COLOR_ARGB(a, r, g, b) ((rw::uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
|
||||||
|
|
||||||
|
|
|
@ -731,14 +731,24 @@ struct Clump
|
||||||
void render(void);
|
void render(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// used by enumerateLights for lighting callback
|
||||||
|
struct WorldLights
|
||||||
|
{
|
||||||
|
RGBAf ambient; // all ambients added
|
||||||
|
int32 numDirectionals;
|
||||||
|
Light **directionals; // only directionals
|
||||||
|
int32 numLocals;
|
||||||
|
Light **locals; // points, (soft)spots
|
||||||
|
};
|
||||||
|
|
||||||
// A bit of a stub right now
|
// A bit of a stub right now
|
||||||
struct World
|
struct World
|
||||||
{
|
{
|
||||||
PLUGINBASE
|
PLUGINBASE
|
||||||
enum { ID = 7 };
|
enum { ID = 7 };
|
||||||
Object object;
|
Object object;
|
||||||
LinkList lights; // these have positions (type >= 0x80)
|
LinkList localLights; // these have positions (type >= 0x80)
|
||||||
LinkList directionalLights; // these do not (type < 0x80)
|
LinkList globalLights; // these do not (type < 0x80)
|
||||||
LinkList clumps;
|
LinkList clumps;
|
||||||
|
|
||||||
static int32 numAllocated;
|
static int32 numAllocated;
|
||||||
|
@ -754,6 +764,7 @@ struct World
|
||||||
void addClump(Clump *clump);
|
void addClump(Clump *clump);
|
||||||
void removeClump(Clump *clump);
|
void removeClump(Clump *clump);
|
||||||
void render(void);
|
void render(void);
|
||||||
|
void enumerateLights(Atomic *atomic, WorldLights *lightData);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TexDictionary
|
struct TexDictionary
|
||||||
|
|
|
@ -28,8 +28,8 @@ World::create(void)
|
||||||
}
|
}
|
||||||
numAllocated++;
|
numAllocated++;
|
||||||
world->object.init(World::ID, 0);
|
world->object.init(World::ID, 0);
|
||||||
world->lights.init();
|
world->localLights.init();
|
||||||
world->directionalLights.init();
|
world->globalLights.init();
|
||||||
world->clumps.init();
|
world->clumps.init();
|
||||||
s_plglist.construct(world);
|
s_plglist.construct(world);
|
||||||
return world;
|
return world;
|
||||||
|
@ -46,11 +46,12 @@ World::destroy(void)
|
||||||
void
|
void
|
||||||
World::addLight(Light *light)
|
World::addLight(Light *light)
|
||||||
{
|
{
|
||||||
|
assert(light->world == nil);
|
||||||
light->world = this;
|
light->world = this;
|
||||||
if(light->getType() < Light::POINT){
|
if(light->getType() < Light::POINT){
|
||||||
this->directionalLights.append(&light->inWorld);
|
this->globalLights.append(&light->inWorld);
|
||||||
}else{
|
}else{
|
||||||
this->lights.append(&light->inWorld);
|
this->localLights.append(&light->inWorld);
|
||||||
if(light->getFrame())
|
if(light->getFrame())
|
||||||
light->getFrame()->updateObjects();
|
light->getFrame()->updateObjects();
|
||||||
}
|
}
|
||||||
|
@ -59,8 +60,9 @@ World::addLight(Light *light)
|
||||||
void
|
void
|
||||||
World::removeLight(Light *light)
|
World::removeLight(Light *light)
|
||||||
{
|
{
|
||||||
if(light->world == this)
|
assert(light->world == this);
|
||||||
light->inWorld.remove();
|
light->inWorld.remove();
|
||||||
|
light->world = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -75,7 +77,7 @@ World::addCamera(Camera *cam)
|
||||||
void
|
void
|
||||||
World::removeCamera(Camera *cam)
|
World::removeCamera(Camera *cam)
|
||||||
{
|
{
|
||||||
if(cam->world == this)
|
assert(cam->world == this);
|
||||||
cam->world = nil;
|
cam->world = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,4 +138,58 @@ World::render(void)
|
||||||
Clump::fromWorld(lnk)->render();
|
Clump::fromWorld(lnk)->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find lights that illuminate an atomic
|
||||||
|
void
|
||||||
|
World::enumerateLights(Atomic *atomic, WorldLights *lightData)
|
||||||
|
{
|
||||||
|
int32 maxDirectionals, maxLocals;
|
||||||
|
|
||||||
|
assert(atomic->world == this);
|
||||||
|
|
||||||
|
maxDirectionals = lightData->numDirectionals;
|
||||||
|
maxLocals = lightData->numLocals;
|
||||||
|
|
||||||
|
lightData->numDirectionals = 0;
|
||||||
|
lightData->numLocals = 0;
|
||||||
|
lightData->ambient.red = 0.0f;
|
||||||
|
lightData->ambient.green = 0.0f;
|
||||||
|
lightData->ambient.blue = 0.0f;
|
||||||
|
lightData->ambient.alpha = 1.0f;
|
||||||
|
|
||||||
|
bool32 normals = atomic->geometry->flags & Geometry::NORMALS;
|
||||||
|
|
||||||
|
FORLIST(lnk, this->globalLights){
|
||||||
|
Light *l = Light::fromWorld(lnk);
|
||||||
|
if((l->getFlags() & Light::LIGHTATOMICS) == 0)
|
||||||
|
continue;
|
||||||
|
if(l->getType() == Light::AMBIENT){
|
||||||
|
lightData->ambient.red += l->color.red;
|
||||||
|
lightData->ambient.green += l->color.green;
|
||||||
|
lightData->ambient.blue += l->color.blue;
|
||||||
|
}else if(normals && l->getType() == Light::DIRECTIONAL){
|
||||||
|
if(lightData->numDirectionals < maxDirectionals)
|
||||||
|
lightData->directionals[lightData->numDirectionals++] = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!normals)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: for this we would use an atomic's world sectors, but we don't have those yet
|
||||||
|
FORLIST(lnk, this->localLights){
|
||||||
|
if(lightData->numLocals >= maxLocals)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Light *l = Light::fromWorld(lnk);
|
||||||
|
if((l->getFlags() & Light::LIGHTATOMICS) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// check if spheres are intersecting
|
||||||
|
Sphere *atomsphere = atomic->getWorldBoundingSphere();
|
||||||
|
V3d dist = sub(l->getFrame()->getLTM()->pos, atomsphere->center);
|
||||||
|
if(length(dist) < atomsphere->radius + l->radius)
|
||||||
|
lightData->locals[lightData->numLocals++] = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,19 @@ initFont(void)
|
||||||
{
|
{
|
||||||
vga.tex = Texture::read("Bm437_IBM_VGA8", "");
|
vga.tex = Texture::read("Bm437_IBM_VGA8", "");
|
||||||
bios.tex = Texture::read("Bm437_IBM_BIOS", "");
|
bios.tex = Texture::read("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");
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -27,6 +27,8 @@ void genIm3DEnd(void);
|
||||||
void initFont(void);
|
void initFont(void);
|
||||||
void printScreen(const char *s, float x, float y);
|
void printScreen(const char *s, float x, float y);
|
||||||
|
|
||||||
|
rw::Charset *testfont;
|
||||||
|
|
||||||
//#include <Windows.h>
|
//#include <Windows.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -177,9 +179,18 @@ InitRW(void)
|
||||||
if(!sk::InitRW())
|
if(!sk::InitRW())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
rw::d3d::isP8supported = false;
|
||||||
|
|
||||||
initFont();
|
initFont();
|
||||||
|
|
||||||
rw::d3d::isP8supported = false;
|
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("maze", nil);
|
tex = rw::Texture::read("maze", nil);
|
||||||
tex2 = rw::Texture::read("checkers", nil);
|
tex2 = rw::Texture::read("checkers", nil);
|
||||||
|
|
||||||
|
@ -327,7 +338,8 @@ im3dtest(void)
|
||||||
verts[i].setV(vs[i].v);
|
verts[i].setV(vs[i].v);
|
||||||
}
|
}
|
||||||
|
|
||||||
rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
|
// rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
|
||||||
|
rw::SetRenderStatePtr(rw::TEXTURERASTER, testfont->raster);
|
||||||
// rw::SetRenderStatePtr(rw::TEXTURERASTER, frontbuffer->raster);
|
// rw::SetRenderStatePtr(rw::TEXTURERASTER, frontbuffer->raster);
|
||||||
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
|
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
|
||||||
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
|
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
|
||||||
|
@ -392,6 +404,7 @@ extern void endSoftras(void);
|
||||||
im3dtest();
|
im3dtest();
|
||||||
// printScreen("Hello, World!", 10, 10);
|
// printScreen("Hello, World!", 10, 10);
|
||||||
|
|
||||||
|
testfont->print("foo ABC", 200, 200, true);
|
||||||
|
|
||||||
camera->m_rwcam->endUpdate();
|
camera->m_rwcam->endUpdate();
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ enumLights(Matrix *lightmat)
|
||||||
ambLight.alpha = 0.0;
|
ambLight.alpha = 0.0;
|
||||||
numDirectionals = 0;
|
numDirectionals = 0;
|
||||||
// only unpositioned lights right now
|
// only unpositioned lights right now
|
||||||
FORLIST(lnk, world->directionalLights){
|
FORLIST(lnk, world->globalLights){
|
||||||
Light *l = Light::fromWorld(lnk);
|
Light *l = Light::fromWorld(lnk);
|
||||||
if(l->getType() == Light::DIRECTIONAL){
|
if(l->getType() == Light::DIRECTIONAL){
|
||||||
if(numDirectionals >= MAX_LIGHTS)
|
if(numDirectionals >= MAX_LIGHTS)
|
||||||
|
|
|
@ -155,6 +155,10 @@ AppEventHandler(sk::Event e, void *param)
|
||||||
return EVENTPROCESSED;
|
return EVENTPROCESSED;
|
||||||
case RESIZE:
|
case RESIZE:
|
||||||
r = (Rect*)param;
|
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.width = r->w;
|
||||||
sk::globals.height = r->h;
|
sk::globals.height = r->h;
|
||||||
// TODO: set aspect ratio
|
// TODO: set aspect ratio
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,365 @@
|
||||||
|
#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;
|
||||||
|
float FOV = 70.0f;
|
||||||
|
|
||||||
|
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::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::V3d LightPos = {0.0f, 0.0f, 75.0f};
|
||||||
|
|
||||||
|
void
|
||||||
|
Init(void)
|
||||||
|
{
|
||||||
|
sk::globals.windowtitle = "Light 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
InitRW(void)
|
||||||
|
{
|
||||||
|
// rw::platform = rw::PLATFORM_D3D8;
|
||||||
|
if(!sk::InitRW())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Scene.world = rw::World::create();
|
||||||
|
|
||||||
|
BaseAmbientLight = CreateBaseAmbientLight();
|
||||||
|
AmbientLight = CreateAmbientLight();
|
||||||
|
DirectLight = CreateDirectLight();
|
||||||
|
PointLight = CreatePointLight();
|
||||||
|
SpotLight = CreateSpotLight();
|
||||||
|
SpotSoftLight = CreateSpotSoftLight();
|
||||||
|
|
||||||
|
Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
|
||||||
|
Scene.camera->setNearPlane(0.1f);
|
||||||
|
Scene.camera->setFarPlane(300.0f);
|
||||||
|
Scene.camera->setFOV(FOV, (float)sk::globals.width/sk::globals.height);
|
||||||
|
Scene.world->addCamera(Scene.camera);
|
||||||
|
|
||||||
|
CreateTestScene(Scene.world);
|
||||||
|
|
||||||
|
ImGui_ImplRW_Init();
|
||||||
|
ImGui::StyleColorsClassic();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SwitchToLight(rw::Light *light)
|
||||||
|
{
|
||||||
|
if(CurrentLight)
|
||||||
|
Scene.world->removeLight(CurrentLight);
|
||||||
|
CurrentLight = light;
|
||||||
|
Scene.world->addLight(CurrentLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Gui(void)
|
||||||
|
{
|
||||||
|
// ImGui::ShowDemoWindow(&show_demo_window);
|
||||||
|
|
||||||
|
static bool showLightWindow = true;
|
||||||
|
ImGui::Begin("Lights", &showLightWindow);
|
||||||
|
static int lightswitch = 0;
|
||||||
|
if(ImGui::RadioButton("Light Off", &lightswitch, 0)){
|
||||||
|
if(CurrentLight)
|
||||||
|
Scene.world->removeLight(CurrentLight);
|
||||||
|
CurrentLight = nil;
|
||||||
|
}
|
||||||
|
if(ImGui::RadioButton("Ambient Light", &lightswitch, 1)){
|
||||||
|
SwitchToLight(AmbientLight);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::RadioButton("Directional Light", &lightswitch, 2)){
|
||||||
|
SwitchToLight(DirectLight);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::RadioButton("Point Light", &lightswitch, 3)){
|
||||||
|
SwitchToLight(PointLight);
|
||||||
|
}
|
||||||
|
if(ImGui::RadioButton("Spot Light", &lightswitch, 4)){
|
||||||
|
SwitchToLight(SpotLight);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::RadioButton("Soft Spot Light", &lightswitch, 5)){
|
||||||
|
SwitchToLight(SpotSoftLight);
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Draw(float timeDelta)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
Scene.world->render();
|
||||||
|
|
||||||
|
Gui();
|
||||||
|
|
||||||
|
ImGui::EndFrame();
|
||||||
|
ImGui::Render();
|
||||||
|
|
||||||
|
Scene.camera->endUpdate();
|
||||||
|
Scene.camera->showRaster();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
if(Scene.camera){
|
||||||
|
sk::CameraSize(Scene.camera, r);
|
||||||
|
Scene.camera->setFOV(FOV, (float)sk::globals.width/sk::globals.height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDLE:
|
||||||
|
Draw(*(float*)param);
|
||||||
|
return EVENTPROCESSED;
|
||||||
|
}
|
||||||
|
return sk::EVENTNOTPROCESSED;
|
||||||
|
}
|
Loading…
Reference in New Issue