librw/tools/clumpview/tests.cpp

135 lines
3.4 KiB
C++

#include <rw.h>
#include <skeleton.h>
using namespace rw;
//
// This is a test to implement T&L in software and render with Im2D
#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->directionalLights){
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;
}
}
}
static void
drawAtomic(Atomic *a)
{
using namespace RWDEVICE;
Im2DVertex *im2dverts;
V3d *xvert;
Matrix xform;
Matrix lightmat;
Camera *cam = (Camera*)engine->currentCamera;
Geometry *g = a->geometry;
MeshHeader *mh = g->meshHeader;
Mesh *m = mh->getMeshes();
int32 width = cam->frameBuffer->width;
int32 height = cam->frameBuffer->height;
RGBA *prelight;
V3d *normals;
TexCoords *texcoords;
Matrix::mult(&xform, a->getFrame()->getLTM(), &cam->viewMatrix);
Matrix::invert(&lightmat, a->getFrame()->getLTM());
enumLights(&lightmat);
xvert = rwNewT(V3d, g->numVertices, MEMDUR_FUNCTION);
im2dverts = rwNewT(Im2DVertex, g->numVertices, MEMDUR_FUNCTION);
prelight = g->colors;
normals = g->morphTargets[0].normals;
texcoords = g->texCoords[0];
V3d::transformPoints(xvert, g->morphTargets[0].vertices, g->numVertices, &xform);
for(int32 i = 0; i < g->numVertices; i++){
float32 recipZ = 1.0f/xvert[i].z;
im2dverts[i].setScreenX(xvert[i].x * recipZ * width);
im2dverts[i].setScreenY((xvert[i].y * recipZ * height));
im2dverts[i].setScreenZ(recipZ * cam->zScale + cam->zShift);
im2dverts[i].setCameraZ(xvert[i].z);
im2dverts[i].setRecipCameraZ(recipZ);
im2dverts[i].setColor(255, 0, 0, 255);
im2dverts[i].setU(texcoords[i].u);
im2dverts[i].setV(texcoords[i].v);
}
for(int32 i = 0; i < mh->numMeshes; i++){
for(int32 j = 0; j < m[i].numIndices; j++){
int32 idx = m[i].indices[j];
RGBA col;
RGBAf colf, color;
if(prelight)
convColor(&color, &prelight[idx]);
else{
color.red = color.green = color.blue = 0.0f;
color.alpha = 1.0f;
}
color = add(color, ambLight);
if(normals)
for(int32 k = 0; k < numDirectionals; k++){
float32 f = dot(normals[idx], neg(directionals[k].at));
if(f <= 0.0f) continue;
colf = scale(directionals[k].color, f);
color = add(color, colf);
}
convColor(&colf, &m[i].material->color);
color = modulate(color, colf);
clamp(&color);
convColor(&col, &color);
im2dverts[idx].setColor(col.red, col.green, col.blue, col.alpha);
}
engine->imtexture = m[i].material->texture;
rw::engine->device.im2DRenderIndexedPrimitive(rw::PRIMTYPETRILIST,
im2dverts, g->numVertices, m[i].indices, m[i].numIndices);
}
rwFree(xvert);
rwFree(im2dverts);
}
void
tlTest(Clump *clump)
{
FORLIST(lnk, clump->atomics){
Atomic *a = Atomic::fromClump(lnk);
drawAtomic(a);
}
}