mirror of https://github.com/aap/librw.git
201 lines
5.1 KiB
C++
201 lines
5.1 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, recipZ);
|
|
im2dverts[i].setV(texcoords[i].v, recipZ);
|
|
}
|
|
for(int32 i = 0; i < mh->numMeshes; i++){
|
|
for(uint32 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);
|
|
}
|
|
|
|
rw::Texture *tex = m[i].material->texture;
|
|
if(tex && tex->raster){
|
|
rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
|
|
rw::SetRenderState(rw::TEXTUREADDRESSU, tex->getAddressU());
|
|
rw::SetRenderState(rw::TEXTUREADDRESSV, tex->getAddressV());
|
|
rw::SetRenderState(rw::TEXTUREFILTER, tex->getFilter());
|
|
}else
|
|
rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
|
|
|
|
im2d::RenderIndexedPrimitive(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);
|
|
}
|
|
}
|
|
|
|
static RWDEVICE::Im2DVertex *clipverts;
|
|
static int32 numClipverts;
|
|
|
|
void
|
|
genIm3DTransform(void *vertices, int32 numVertices, Matrix *world)
|
|
{
|
|
using namespace RWDEVICE;
|
|
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;
|
|
}
|