mirror of
https://github.com/aap/librw.git
synced 2024-12-01 08:05:42 +00:00
fixed sky mipmap stream write; experimented with software pipeline
This commit is contained in:
parent
b1c3c1dca8
commit
c62c1464d7
@ -383,6 +383,7 @@ rasterCreateTexture(Raster *raster)
|
|||||||
}else
|
}else
|
||||||
format = formatInfo[(raster->format >> 8) & 0xF].d3dformat;
|
format = formatInfo[(raster->format >> 8) & 0xF].d3dformat;
|
||||||
natras->format = format;
|
natras->format = format;
|
||||||
|
raster->depth = formatInfo[(raster->format >> 8) & 0xF].depth;
|
||||||
natras->hasAlpha = formatInfo[(raster->format >> 8) & 0xF].hasAlpha;
|
natras->hasAlpha = formatInfo[(raster->format >> 8) & 0xF].hasAlpha;
|
||||||
levels = Raster::calculateNumLevels(raster->width, raster->height);
|
levels = Raster::calculateNumLevels(raster->width, raster->height);
|
||||||
natras->texture = createTexture(raster->width, raster->height,
|
natras->texture = createTexture(raster->width, raster->height,
|
||||||
|
@ -1064,6 +1064,9 @@ Device renderdevice = {
|
|||||||
d3d::showRaster,
|
d3d::showRaster,
|
||||||
d3d::setRwRenderState,
|
d3d::setRwRenderState,
|
||||||
d3d::getRwRenderState,
|
d3d::getRwRenderState,
|
||||||
|
d3d::im2DRenderLine,
|
||||||
|
d3d::im2DRenderTriangle,
|
||||||
|
d3d::im2DRenderPrimitive,
|
||||||
d3d::im2DRenderIndexedPrimitive,
|
d3d::im2DRenderIndexedPrimitive,
|
||||||
d3d::im3DTransform,
|
d3d::im3DTransform,
|
||||||
d3d::im3DRenderIndexed,
|
d3d::im3DRenderIndexed,
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "../rwengine.h"
|
#include "../rwengine.h"
|
||||||
#include "rwd3d.h"
|
#include "rwd3d.h"
|
||||||
#include "rwd3d9.h"
|
#include "rwd3d9.h"
|
||||||
|
#include "rwd3dimpl.h"
|
||||||
|
|
||||||
namespace rw {
|
namespace rw {
|
||||||
namespace d3d {
|
namespace d3d {
|
||||||
@ -56,6 +57,73 @@ closeIm2D(void)
|
|||||||
deleteObject(im2dindbuf);
|
deleteObject(im2dindbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Im2DVertex tmpprimbuf[3];
|
||||||
|
|
||||||
|
void
|
||||||
|
im2DRenderLine(void *vertices, int32 numVertices, int32 vert1, int32 vert2)
|
||||||
|
{
|
||||||
|
Im2DVertex *verts = (Im2DVertex*)vertices;
|
||||||
|
tmpprimbuf[0] = verts[vert1];
|
||||||
|
tmpprimbuf[1] = verts[vert2];
|
||||||
|
im2DRenderPrimitive(PRIMTYPELINELIST, tmpprimbuf, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
im2DRenderTriangle(void *vertices, int32 numVertices, int32 vert1, int32 vert2, int32 vert3)
|
||||||
|
{
|
||||||
|
Im2DVertex *verts = (Im2DVertex*)vertices;
|
||||||
|
tmpprimbuf[0] = verts[vert1];
|
||||||
|
tmpprimbuf[1] = verts[vert2];
|
||||||
|
tmpprimbuf[2] = verts[vert3];
|
||||||
|
im2DRenderPrimitive(PRIMTYPETRILIST, tmpprimbuf, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices)
|
||||||
|
{
|
||||||
|
if(numVertices > NUMVERTICES){
|
||||||
|
// TODO: error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8 *lockedvertices = lockVertices(im2dvertbuf, 0, numVertices*sizeof(Im2DVertex), D3DLOCK_NOSYSLOCK);
|
||||||
|
memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertex));
|
||||||
|
unlockVertices(im2dvertbuf);
|
||||||
|
|
||||||
|
d3ddevice->SetStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex));
|
||||||
|
d3ddevice->SetVertexDeclaration(im2ddecl);
|
||||||
|
setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||||
|
setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||||
|
setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
||||||
|
setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||||
|
setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||||
|
setTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
|
||||||
|
|
||||||
|
d3d::flushCache();
|
||||||
|
|
||||||
|
uint32 primCount = 0;
|
||||||
|
switch(primType){
|
||||||
|
case PRIMTYPELINELIST:
|
||||||
|
primCount = numVertices/2;
|
||||||
|
break;
|
||||||
|
case PRIMTYPEPOLYLINE:
|
||||||
|
primCount = numVertices-1;
|
||||||
|
break;
|
||||||
|
case PRIMTYPETRILIST:
|
||||||
|
primCount = numVertices/3;
|
||||||
|
break;
|
||||||
|
case PRIMTYPETRISTRIP:
|
||||||
|
primCount = numVertices-2;
|
||||||
|
break;
|
||||||
|
case PRIMTYPETRIFAN:
|
||||||
|
primCount = numVertices-2;
|
||||||
|
break;
|
||||||
|
case PRIMTYPEPOINTLIST:
|
||||||
|
primCount = numVertices;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
d3ddevice->DrawPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0, primCount);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
im2DRenderIndexedPrimitive(PrimitiveType primType,
|
im2DRenderIndexedPrimitive(PrimitiveType primType,
|
||||||
void *vertices, int32 numVertices, void *indices, int32 numIndices)
|
void *vertices, int32 numVertices, void *indices, int32 numIndices)
|
||||||
|
@ -32,10 +32,16 @@ struct Im3DVertex
|
|||||||
void setY(float32 y) { this->position.y = y; }
|
void setY(float32 y) { this->position.y = y; }
|
||||||
void setZ(float32 z) { this->position.z = z; }
|
void setZ(float32 z) { this->position.z = z; }
|
||||||
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = D3DCOLOR_ARGB(a, r, g, b); }
|
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = D3DCOLOR_ARGB(a, r, g, b); }
|
||||||
RGBA getColor(void) { return makeRGBA(this->color>>16 & 0xFF, this->color>>8 & 0xFF,
|
|
||||||
this->color & 0xFF, this->color>>24 & 0xFF); }
|
|
||||||
void setU(float32 u) { this->u = u; }
|
void setU(float32 u) { this->u = u; }
|
||||||
void setV(float32 v) { this->v = v; }
|
void setV(float32 v) { this->v = v; }
|
||||||
|
|
||||||
|
float getX(void) { return this->position.x; }
|
||||||
|
float getY(void) { return this->position.y; }
|
||||||
|
float getZ(void) { return this->position.z; }
|
||||||
|
RGBA getColor(void) { return makeRGBA(this->color>>16 & 0xFF, this->color>>8 & 0xFF,
|
||||||
|
this->color & 0xFF, this->color>>24 & 0xFF); }
|
||||||
|
float getU(void) { return this->u; }
|
||||||
|
float getV(void) { return this->v; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Im2DVertex
|
struct Im2DVertex
|
||||||
@ -53,6 +59,15 @@ struct Im2DVertex
|
|||||||
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = D3DCOLOR_ARGB(a, r, g, b); }
|
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = D3DCOLOR_ARGB(a, r, g, b); }
|
||||||
void setU(float32 u, float recipZ) { this->u = u; }
|
void setU(float32 u, float recipZ) { this->u = u; }
|
||||||
void setV(float32 v, float recipZ) { this->v = v; }
|
void setV(float32 v, float recipZ) { this->v = v; }
|
||||||
|
|
||||||
|
float getScreenX(void) { return this->x; }
|
||||||
|
float getScreenY(void) { return this->y; }
|
||||||
|
float getScreenZ(void) { return this->z; }
|
||||||
|
float getCameraZ(void) { return this->w; }
|
||||||
|
RGBA getColor(void) { return makeRGBA(this->color>>16 & 0xFF, this->color>>8 & 0xFF,
|
||||||
|
this->color & 0xFF, this->color>>24 & 0xFF); }
|
||||||
|
float getU(void) { return this->u; }
|
||||||
|
float getV(void) { return this->v; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void setD3dMaterial(D3DMATERIAL9 *mat9);
|
void setD3dMaterial(D3DMATERIAL9 *mat9);
|
||||||
|
@ -4,6 +4,12 @@ namespace d3d {
|
|||||||
#ifdef RW_D3D9
|
#ifdef RW_D3D9
|
||||||
void openIm2D(void);
|
void openIm2D(void);
|
||||||
void closeIm2D(void);
|
void closeIm2D(void);
|
||||||
|
void im2DRenderLine(void *vertices, int32 numVertices,
|
||||||
|
int32 vert1, int32 vert2);
|
||||||
|
void im2DRenderTriangle(void *vertices, int32 numVertices,
|
||||||
|
int32 vert1, int32 vert2, int32 vert3);
|
||||||
|
void im2DRenderPrimitive(PrimitiveType primType,
|
||||||
|
void *vertices, int32 numVertices);
|
||||||
void im2DRenderIndexedPrimitive(PrimitiveType primType,
|
void im2DRenderIndexedPrimitive(PrimitiveType primType,
|
||||||
void *vertices, int32 numVertices, void *indices, int32 numIndices);
|
void *vertices, int32 numVertices, void *indices, int32 numIndices);
|
||||||
|
|
||||||
|
@ -209,6 +209,9 @@ void showRaster(Raster*) { }
|
|||||||
void setRenderState(int32, void*) { }
|
void setRenderState(int32, void*) { }
|
||||||
void *getRenderState(int32) { return 0; }
|
void *getRenderState(int32) { return 0; }
|
||||||
|
|
||||||
|
void im2DRenderLine(void*, int32, int32, int32) { }
|
||||||
|
void im2DRenderTriangle(void*, int32, int32, int32, int32) { }
|
||||||
|
void im2DRenderPrimitive(PrimitiveType, void*, int32) { }
|
||||||
void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32) { }
|
void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32) { }
|
||||||
|
|
||||||
void im3DTransform(void *vertices, int32 numVertices, Matrix *world) { }
|
void im3DTransform(void *vertices, int32 numVertices, Matrix *world) { }
|
||||||
@ -268,6 +271,9 @@ Device renderdevice = {
|
|||||||
null::showRaster,
|
null::showRaster,
|
||||||
null::setRenderState,
|
null::setRenderState,
|
||||||
null::getRenderState,
|
null::getRenderState,
|
||||||
|
null::im2DRenderLine,
|
||||||
|
null::im2DRenderTriangle,
|
||||||
|
null::im2DRenderPrimitive,
|
||||||
null::im2DRenderIndexedPrimitive,
|
null::im2DRenderIndexedPrimitive,
|
||||||
null::im3DTransform,
|
null::im3DTransform,
|
||||||
null::im3DRenderIndexed,
|
null::im3DRenderIndexed,
|
||||||
|
@ -859,6 +859,9 @@ Device renderdevice = {
|
|||||||
gl3::showRaster,
|
gl3::showRaster,
|
||||||
gl3::setRenderState,
|
gl3::setRenderState,
|
||||||
gl3::getRenderState,
|
gl3::getRenderState,
|
||||||
|
gl3::im2DRenderLine,
|
||||||
|
gl3::im2DRenderTriangle,
|
||||||
|
gl3::im2DRenderPrimitive,
|
||||||
gl3::im2DRenderIndexedPrimitive,
|
gl3::im2DRenderIndexedPrimitive,
|
||||||
gl3::im3DTransform,
|
gl3::im3DTransform,
|
||||||
gl3::im3DRenderIndexed,
|
gl3::im3DRenderIndexed,
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#ifdef RW_OPENGL
|
#ifdef RW_OPENGL
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include "rwgl3.h"
|
#include "rwgl3.h"
|
||||||
|
#include "rwgl3impl.h"
|
||||||
#include "rwgl3shader.h"
|
#include "rwgl3shader.h"
|
||||||
|
|
||||||
namespace rw {
|
namespace rw {
|
||||||
@ -73,6 +74,53 @@ closeIm2D(void)
|
|||||||
im2dShader = nil;
|
im2dShader = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Im2DVertex tmpprimbuf[3];
|
||||||
|
|
||||||
|
void
|
||||||
|
im2DRenderLine(void *vertices, int32 numVertices, int32 vert1, int32 vert2)
|
||||||
|
{
|
||||||
|
Im2DVertex *verts = (Im2DVertex*)vertices;
|
||||||
|
tmpprimbuf[0] = verts[vert1];
|
||||||
|
tmpprimbuf[1] = verts[vert2];
|
||||||
|
im2DRenderPrimitive(PRIMTYPELINELIST, tmpprimbuf, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
im2DRenderTriangle(void *vertices, int32 numVertices, int32 vert1, int32 vert2, int32 vert3)
|
||||||
|
{
|
||||||
|
Im2DVertex *verts = (Im2DVertex*)vertices;
|
||||||
|
tmpprimbuf[0] = verts[vert1];
|
||||||
|
tmpprimbuf[1] = verts[vert2];
|
||||||
|
tmpprimbuf[2] = verts[vert3];
|
||||||
|
im2DRenderPrimitive(PRIMTYPETRILIST, tmpprimbuf, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices)
|
||||||
|
{
|
||||||
|
GLfloat xform[4];
|
||||||
|
Camera *cam;
|
||||||
|
cam = (Camera*)engine->currentCamera;
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, im2DVbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex),
|
||||||
|
vertices, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
xform[0] = 2.0f/cam->frameBuffer->width;
|
||||||
|
xform[1] = -2.0f/cam->frameBuffer->height;
|
||||||
|
xform[2] = -1.0f;
|
||||||
|
xform[3] = 1.0f;
|
||||||
|
|
||||||
|
im2dShader->use();
|
||||||
|
setAttribPointers(im2dattribDesc, 3);
|
||||||
|
|
||||||
|
glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform);
|
||||||
|
|
||||||
|
flushCache();
|
||||||
|
glDrawArrays(primTypeMap[primType], 0, numVertices);
|
||||||
|
disableAttribPointers(im2dattribDesc, 3);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
im2DRenderIndexedPrimitive(PrimitiveType primType,
|
im2DRenderIndexedPrimitive(PrimitiveType primType,
|
||||||
void *vertices, int32 numVertices,
|
void *vertices, int32 numVertices,
|
||||||
|
@ -96,9 +96,15 @@ struct Im3DVertex
|
|||||||
void setZ(float32 z) { this->position.z = z; }
|
void setZ(float32 z) { this->position.z = z; }
|
||||||
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) {
|
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) {
|
||||||
this->r = r; this->g = g; this->b = b; this->a = a; }
|
this->r = r; this->g = g; this->b = b; this->a = a; }
|
||||||
RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); }
|
|
||||||
void setU(float32 u) { this->u = u; }
|
void setU(float32 u) { this->u = u; }
|
||||||
void setV(float32 v) { this->v = v; }
|
void setV(float32 v) { this->v = v; }
|
||||||
|
|
||||||
|
float getX(void) { return this->position.x; }
|
||||||
|
float getY(void) { return this->position.y; }
|
||||||
|
float getZ(void) { return this->position.z; }
|
||||||
|
RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); }
|
||||||
|
float getU(void) { return this->u; }
|
||||||
|
float getV(void) { return this->v; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Im2DVertex
|
struct Im2DVertex
|
||||||
@ -116,6 +122,14 @@ struct Im2DVertex
|
|||||||
this->r = r; this->g = g; this->b = b; this->a = a; }
|
this->r = r; this->g = g; this->b = b; this->a = a; }
|
||||||
void setU(float32 u, float recipz) { this->u = u; }
|
void setU(float32 u, float recipz) { this->u = u; }
|
||||||
void setV(float32 v, float recipz) { this->v = v; }
|
void setV(float32 v, float recipz) { this->v = v; }
|
||||||
|
|
||||||
|
float getScreenX(void) { return this->x; }
|
||||||
|
float getScreenY(void) { return this->y; }
|
||||||
|
float getScreenZ(void) { return this->z; }
|
||||||
|
float getCameraZ(void) { return this->w; }
|
||||||
|
RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); }
|
||||||
|
float getU(void) { return this->u; }
|
||||||
|
float getV(void) { return this->v; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void setAttribPointers(AttribDesc *attribDescs, int32 numAttribs);
|
void setAttribPointers(AttribDesc *attribDescs, int32 numAttribs);
|
||||||
|
@ -6,6 +6,12 @@ namespace gl3 {
|
|||||||
extern uint32 im2DVbo, im2DIbo;
|
extern uint32 im2DVbo, im2DIbo;
|
||||||
void openIm2D(void);
|
void openIm2D(void);
|
||||||
void closeIm2D(void);
|
void closeIm2D(void);
|
||||||
|
void im2DRenderLine(void *vertices, int32 numVertices,
|
||||||
|
int32 vert1, int32 vert2);
|
||||||
|
void im2DRenderTriangle(void *vertices, int32 numVertices,
|
||||||
|
int32 vert1, int32 vert2, int32 vert3);
|
||||||
|
void im2DRenderPrimitive(PrimitiveType primType,
|
||||||
|
void *vertices, int32 numVertices);
|
||||||
void im2DRenderIndexedPrimitive(PrimitiveType primType,
|
void im2DRenderIndexedPrimitive(PrimitiveType primType,
|
||||||
void *vertices, int32 numVertices, void *indices, int32 numIndices);
|
void *vertices, int32 numVertices, void *indices, int32 numIndices);
|
||||||
|
|
||||||
|
@ -1454,7 +1454,7 @@ unswizzle16to4(uint8 *dst, uint8 *src, int32 w, int32 h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
expandPSMT4(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw)
|
expandPSMT4(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw)
|
||||||
{
|
{
|
||||||
int32 x, y;
|
int32 x, y;
|
||||||
@ -1465,7 +1465,7 @@ expandPSMT4(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
copyPSMT8(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw)
|
copyPSMT8(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw)
|
||||||
{
|
{
|
||||||
int32 x, y;
|
int32 x, y;
|
||||||
@ -1620,7 +1620,7 @@ createNativeRaster(void *object, int32 offset, int32)
|
|||||||
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, object, offset);
|
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, object, offset);
|
||||||
raster->tex0 = 0;
|
raster->tex0 = 0;
|
||||||
raster->paletteBase = 0;
|
raster->paletteBase = 0;
|
||||||
raster->kl = 0xFC0;
|
raster->kl = defaultMipMapKL;
|
||||||
raster->tex1low = 0;
|
raster->tex1low = 0;
|
||||||
raster->unk2 = 0;
|
raster->unk2 = 0;
|
||||||
raster->miptbp1 = 0;
|
raster->miptbp1 = 0;
|
||||||
@ -1668,8 +1668,10 @@ static Stream*
|
|||||||
writeMipmap(Stream *stream, int32, void *object, int32 offset, int32)
|
writeMipmap(Stream *stream, int32, void *object, int32 offset, int32)
|
||||||
{
|
{
|
||||||
Texture *tex = (Texture*)object;
|
Texture *tex = (Texture*)object;
|
||||||
if(tex->raster)
|
if(tex->raster){
|
||||||
return nil;
|
stream->writeI32(defaultMipMapKL);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, tex->raster, offset);
|
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, tex->raster, offset);
|
||||||
stream->writeI32(raster->kl);
|
stream->writeI32(raster->kl);
|
||||||
return stream;
|
return stream;
|
||||||
@ -1873,6 +1875,10 @@ streamExt.mipmapVal);
|
|||||||
calcTEX1(raster, &tex1, tex->filterAddressing & 0xF);
|
calcTEX1(raster, &tex1, tex->filterAddressing & 0xF);
|
||||||
// printTEX1(tex1);
|
// printTEX1(tex1);
|
||||||
|
|
||||||
|
// TODO: GTA SA LD_OTB.txd loses here
|
||||||
|
assert(natras->pixelSize >= streamExt.pixelSize);
|
||||||
|
assert(natras->paletteSize >= streamExt.paletteSize);
|
||||||
|
|
||||||
natras->tex0 = streamExt.tex0;
|
natras->tex0 = streamExt.tex0;
|
||||||
natras->paletteBase = streamExt.paletteOffset;
|
natras->paletteBase = streamExt.paletteOffset;
|
||||||
natras->tex1low = streamExt.tex1low;
|
natras->tex1low = streamExt.tex1low;
|
||||||
|
@ -220,5 +220,8 @@ Texture *readNativeTexture(Stream *stream);
|
|||||||
void writeNativeTexture(Texture *tex, Stream *stream);
|
void writeNativeTexture(Texture *tex, Stream *stream);
|
||||||
uint32 getSizeNativeTexture(Texture *tex);
|
uint32 getSizeNativeTexture(Texture *tex);
|
||||||
|
|
||||||
|
void expandPSMT4(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw);
|
||||||
|
void copyPSMT8(uint8 *dst, uint8 *src, int32 w, int32 h, int32 srcw);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,25 @@ namespace im2d {
|
|||||||
float32 GetNearZ(void) { return engine->device.zNear; }
|
float32 GetNearZ(void) { return engine->device.zNear; }
|
||||||
float32 GetFarZ(void) { return engine->device.zFar; }
|
float32 GetFarZ(void) { return engine->device.zFar; }
|
||||||
void
|
void
|
||||||
|
RenderLine(void *verts, int32 numVerts, int32 vert1, int32 vert2)
|
||||||
|
{
|
||||||
|
engine->device.im2DRenderLine(verts, numVerts, vert1, vert2);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
RenderTriangle(void *verts, int32 numVerts, int32 vert1, int32 vert2, int32 vert3)
|
||||||
|
{
|
||||||
|
engine->device.im2DRenderTriangle(verts, numVerts, vert1, vert2, vert3);
|
||||||
|
}
|
||||||
|
void
|
||||||
RenderIndexedPrimitive(PrimitiveType type, void *verts, int32 numVerts, void *indices, int32 numIndices)
|
RenderIndexedPrimitive(PrimitiveType type, void *verts, int32 numVerts, void *indices, int32 numIndices)
|
||||||
{
|
{
|
||||||
engine->device.im2DRenderIndexedPrimitive(type, verts, numVerts, indices, numIndices);
|
engine->device.im2DRenderIndexedPrimitive(type, verts, numVerts, indices, numIndices);
|
||||||
}
|
}
|
||||||
|
void
|
||||||
|
RenderPrimitive(PrimitiveType type, void *verts, int32 numVerts)
|
||||||
|
{
|
||||||
|
engine->device.im2DRenderPrimitive(type, verts, numVerts);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,9 +36,10 @@ struct Device
|
|||||||
void (*setRenderState)(int32 state, void *value);
|
void (*setRenderState)(int32 state, void *value);
|
||||||
void *(*getRenderState)(int32 state);
|
void *(*getRenderState)(int32 state);
|
||||||
|
|
||||||
// TODO: render line
|
void (*im2DRenderLine)(void*, int32, int32, int32);
|
||||||
// TODO: render triangle
|
void (*im2DRenderTriangle)(void*, int32, int32, int32, int32);
|
||||||
// TODO: render primitive
|
void (*im2DRenderPrimitive)(PrimitiveType,
|
||||||
|
void*, int32);
|
||||||
void (*im2DRenderIndexedPrimitive)(PrimitiveType,
|
void (*im2DRenderIndexedPrimitive)(PrimitiveType,
|
||||||
void*, int32, void*, int32);
|
void*, int32, void*, int32);
|
||||||
|
|
||||||
@ -163,6 +164,9 @@ namespace null {
|
|||||||
void rasterFromImage(Raster*, Image*);
|
void rasterFromImage(Raster*, Image*);
|
||||||
Image *rasterToImage(Raster*);
|
Image *rasterToImage(Raster*);
|
||||||
|
|
||||||
|
void im2DRenderLine(void*, int32, int32, int32);
|
||||||
|
void im2DRenderTriangle(void*, int32, int32, int32, int32);
|
||||||
|
void im2DRenderPrimitive(PrimitiveType, void*, int32);
|
||||||
void im2DRenderIndexedPrimitive(PrimitiveType,
|
void im2DRenderIndexedPrimitive(PrimitiveType,
|
||||||
void*, int32, void*, int32);
|
void*, int32, void*, int32);
|
||||||
|
|
||||||
|
@ -68,7 +68,10 @@ namespace im2d {
|
|||||||
|
|
||||||
float32 GetNearZ(void);
|
float32 GetNearZ(void);
|
||||||
float32 GetFarZ(void);
|
float32 GetFarZ(void);
|
||||||
|
void RenderLine(void *verts, int32 numVerts, int32 vert1, int32 vert2);
|
||||||
|
void RenderTriangle(void *verts, int32 numVerts, int32 vert1, int32 vert2, int32 vert3);
|
||||||
void RenderIndexedPrimitive(PrimitiveType, void *verts, int32 numVerts, void *indices, int32 numIndices);
|
void RenderIndexedPrimitive(PrimitiveType, void *verts, int32 numVerts, void *indices, int32 numIndices);
|
||||||
|
void RenderPrimitive(PrimitiveType type, void *verts, int32 numVerts);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,14 @@ struct SceneGlobals {
|
|||||||
rw::Clump *clump;
|
rw::Clump *clump;
|
||||||
} Scene;
|
} Scene;
|
||||||
rw::Texture *tex, *tex2;
|
rw::Texture *tex, *tex2;
|
||||||
|
rw::Raster *testras;
|
||||||
rw::EngineStartParams engineStartParams;
|
rw::EngineStartParams engineStartParams;
|
||||||
|
|
||||||
|
bool dosoftras = 1;
|
||||||
|
|
||||||
|
namespace gen {
|
||||||
void tlTest(rw::Clump *clump);
|
void tlTest(rw::Clump *clump);
|
||||||
|
}
|
||||||
void genIm3DTransform(void *vertices, rw::int32 numVertices, rw::Matrix *xform);
|
void genIm3DTransform(void *vertices, rw::int32 numVertices, rw::Matrix *xform);
|
||||||
void genIm3DRenderIndexed(rw::PrimitiveType prim, void *indices, rw::int32 numIndices);
|
void genIm3DRenderIndexed(rw::PrimitiveType prim, void *indices, rw::int32 numIndices);
|
||||||
void genIm3DEnd(void);
|
void genIm3DEnd(void);
|
||||||
@ -25,7 +30,7 @@ Init(void)
|
|||||||
{
|
{
|
||||||
sk::globals.windowtitle = "Clump viewer";
|
sk::globals.windowtitle = "Clump viewer";
|
||||||
sk::globals.width = 640;
|
sk::globals.width = 640;
|
||||||
sk::globals.height = 480;
|
sk::globals.height = 448;
|
||||||
sk::globals.quit = 0;
|
sk::globals.quit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +173,7 @@ InitRW(void)
|
|||||||
tex = rw::Texture::read("maze", nil);
|
tex = rw::Texture::read("maze", nil);
|
||||||
tex2 = rw::Texture::read("checkers", nil);
|
tex2 = rw::Texture::read("checkers", nil);
|
||||||
|
|
||||||
const char *filename = "teapot.dff";
|
const char *filename = "teapot2.dff";
|
||||||
if(sk::args.argc > 1)
|
if(sk::args.argc > 1)
|
||||||
filename = sk::args.argv[1];
|
filename = sk::args.argv[1];
|
||||||
rw::StreamFile in;
|
rw::StreamFile in;
|
||||||
@ -196,7 +201,7 @@ InitRW(void)
|
|||||||
Scene.world = rw::World::create();
|
Scene.world = rw::World::create();
|
||||||
|
|
||||||
rw::Light *ambient = rw::Light::create(rw::Light::AMBIENT);
|
rw::Light *ambient = rw::Light::create(rw::Light::AMBIENT);
|
||||||
ambient->setColor(0.2f, 0.2f, 0.2f);
|
ambient->setColor(0.3f, 0.3f, 0.3f);
|
||||||
Scene.world->addLight(ambient);
|
Scene.world->addLight(ambient);
|
||||||
|
|
||||||
rw::V3d xaxis = { 1.0f, 0.0f, 0.0f };
|
rw::V3d xaxis = { 1.0f, 0.0f, 0.0f };
|
||||||
@ -209,9 +214,10 @@ InitRW(void)
|
|||||||
camera = new Camera;
|
camera = new Camera;
|
||||||
Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
|
Scene.camera = sk::CameraCreate(sk::globals.width, sk::globals.height, 1);
|
||||||
camera->m_rwcam = Scene.camera;
|
camera->m_rwcam = Scene.camera;
|
||||||
camera->m_aspectRatio = 640.0f/480.0f;
|
camera->m_aspectRatio = 640.0f/448.0f;
|
||||||
camera->m_near = 0.1f;
|
camera->m_near = 5.0f;
|
||||||
camera->m_far = 450.0f;
|
// camera->m_far = 450.0f;
|
||||||
|
camera->m_far = 15.0f;
|
||||||
camera->m_target.set(0.0f, 0.0f, 0.0f);
|
camera->m_target.set(0.0f, 0.0f, 0.0f);
|
||||||
camera->m_position.set(0.0f, -10.0f, 0.0f);
|
camera->m_position.set(0.0f, -10.0f, 0.0f);
|
||||||
// camera->setPosition(Vec3(0.0f, 5.0f, 0.0f));
|
// camera->setPosition(Vec3(0.0f, 5.0f, 0.0f));
|
||||||
@ -235,16 +241,16 @@ im2dtest(void)
|
|||||||
rw::uint8 r, g, b, a;
|
rw::uint8 r, g, b, a;
|
||||||
float u, v;
|
float u, v;
|
||||||
} vs[4] = {
|
} vs[4] = {
|
||||||
/*
|
|
||||||
{ 0.0f, 0.0f, 255, 0, 0, 128, 0.0f, 0.0f },
|
{ 0.0f, 0.0f, 255, 0, 0, 128, 0.0f, 0.0f },
|
||||||
{ 640.0f, 0.0f, 0, 255, 0, 128, 1.0f, 0.0f },
|
{ 640.0f, 0.0f, 0, 255, 0, 128, 1.0f, 0.0f },
|
||||||
{ 0.0f, 480.0f, 0, 0, 255, 128, 0.0f, 1.0f },
|
{ 0.0f, 448.0f, 0, 0, 255, 128, 0.0f, 1.0f },
|
||||||
{ 640.0f, 480.0f, 0, 255, 255, 128, 1.0f, 1.0f },
|
{ 640.0f, 448.0f, 0, 255, 255, 128, 1.0f, 1.0f },
|
||||||
*/
|
/*
|
||||||
{ 0.0f, 0.0f, 255, 0, 0, 128, 0.0f, 1.0f },
|
{ 0.0f, 0.0f, 255, 0, 0, 128, 0.0f, 1.0f },
|
||||||
{ 640.0f, 0.0f, 0, 255, 0, 128, 0.0f, 0.0f },
|
{ 640.0f, 0.0f, 0, 255, 0, 128, 0.0f, 0.0f },
|
||||||
{ 0.0f, 480.0f, 0, 0, 255, 128, 1.0f, 1.0f },
|
{ 0.0f, 448.0f, 0, 0, 255, 128, 1.0f, 1.0f },
|
||||||
{ 640.0f, 480.0f, 0, 255, 255, 128, 1.0f, 0.0f },
|
{ 640.0f, 448.0f, 0, 255, 255, 128, 1.0f, 0.0f },
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
Im2DVertex verts[4];
|
Im2DVertex verts[4];
|
||||||
static short indices[] = {
|
static short indices[] = {
|
||||||
@ -258,12 +264,14 @@ im2dtest(void)
|
|||||||
verts[i].setScreenZ(rw::im2d::GetNearZ());
|
verts[i].setScreenZ(rw::im2d::GetNearZ());
|
||||||
verts[i].setCameraZ(Scene.camera->nearPlane);
|
verts[i].setCameraZ(Scene.camera->nearPlane);
|
||||||
verts[i].setRecipCameraZ(recipZ);
|
verts[i].setRecipCameraZ(recipZ);
|
||||||
verts[i].setColor(vs[i].r, vs[i].g, vs[i].b, vs[i].a);
|
// verts[i].setColor(vs[i].r, vs[i].g, vs[i].b, vs[i].a);
|
||||||
verts[i].setU(vs[i].u, recipZ);
|
verts[i].setColor(255, 255, 255, 255);
|
||||||
verts[i].setV(vs[i].v, recipZ);
|
verts[i].setU(vs[i].u + 0.5f/640.0f, recipZ);
|
||||||
|
verts[i].setV(vs[i].v + 0.5f/448.0f, recipZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
rw::SetRenderStatePtr(rw::TEXTURERASTER, tex2->raster);
|
// rw::SetRenderStatePtr(rw::TEXTURERASTER, tex2->raster);
|
||||||
|
rw::SetRenderStatePtr(rw::TEXTURERASTER, testras);
|
||||||
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);
|
||||||
rw::SetRenderState(rw::VERTEXALPHA, 1);
|
rw::SetRenderState(rw::VERTEXALPHA, 1);
|
||||||
@ -329,12 +337,24 @@ Draw(float timeDelta)
|
|||||||
camera->update();
|
camera->update();
|
||||||
camera->m_rwcam->beginUpdate();
|
camera->m_rwcam->beginUpdate();
|
||||||
|
|
||||||
Scene.clump->render();
|
extern void beginSoftras(void);
|
||||||
// im2dtest();
|
beginSoftras();
|
||||||
// tlTest(Scene.clump);
|
|
||||||
|
gen::tlTest(Scene.clump);
|
||||||
|
void drawtest(void);
|
||||||
|
// drawtest();
|
||||||
|
|
||||||
|
extern void endSoftras(void);
|
||||||
|
if(dosoftras){
|
||||||
|
endSoftras();
|
||||||
|
im2dtest();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scene.clump->render();
|
||||||
// im3dtest();
|
// im3dtest();
|
||||||
// printScreen("Hello, World!", 10, 10);
|
// printScreen("Hello, World!", 10, 10);
|
||||||
|
|
||||||
|
|
||||||
camera->m_rwcam->endUpdate();
|
camera->m_rwcam->endUpdate();
|
||||||
camera->m_rwcam->showRaster();
|
camera->m_rwcam->showRaster();
|
||||||
}
|
}
|
||||||
@ -379,6 +399,9 @@ KeyDown(int key)
|
|||||||
case 'F':
|
case 'F':
|
||||||
camera->zoom(-0.1f);
|
camera->zoom(-0.1f);
|
||||||
break;
|
break;
|
||||||
|
case 'V':
|
||||||
|
dosoftras = !dosoftras;
|
||||||
|
break;
|
||||||
case sk::KEY_ESC:
|
case sk::KEY_ESC:
|
||||||
sk::globals.quit = 1;
|
sk::globals.quit = 1;
|
||||||
break;
|
break;
|
||||||
@ -432,7 +455,8 @@ AppEventHandler(sk::Event e, void *param)
|
|||||||
|
|
||||||
sk::globals.width = r->w;
|
sk::globals.width = r->w;
|
||||||
sk::globals.height = r->h;
|
sk::globals.height = r->h;
|
||||||
// TODO: set aspect ratio
|
if(camera)
|
||||||
|
camera->m_aspectRatio = (float)r->w/r->h;
|
||||||
if(Scene.camera)
|
if(Scene.camera)
|
||||||
sk::CameraSize(Scene.camera, r);
|
sk::CameraSize(Scene.camera, r);
|
||||||
break;
|
break;
|
||||||
|
900
tools/clumpview/ras_test.cpp
Normal file
900
tools/clumpview/ras_test.cpp
Normal file
@ -0,0 +1,900 @@
|
|||||||
|
#include <rw.h>
|
||||||
|
#include <skeleton.h>
|
||||||
|
|
||||||
|
namespace rs {
|
||||||
|
|
||||||
|
typedef int8_t i8;
|
||||||
|
typedef uint8_t u8;
|
||||||
|
typedef int16_t i16;
|
||||||
|
typedef uint16_t u16;
|
||||||
|
typedef int32_t i32;
|
||||||
|
typedef uint32_t u32;
|
||||||
|
typedef int64_t i64;
|
||||||
|
typedef uint64_t u64;
|
||||||
|
|
||||||
|
typedef struct Canvas Canvas;
|
||||||
|
struct Canvas
|
||||||
|
{
|
||||||
|
u8 *fb;
|
||||||
|
u32 *zbuf;
|
||||||
|
int w, h;
|
||||||
|
};
|
||||||
|
extern Canvas *canvas;
|
||||||
|
|
||||||
|
typedef struct Texture Texture;
|
||||||
|
struct Texture
|
||||||
|
{
|
||||||
|
u8 *pixels;
|
||||||
|
int w, h;
|
||||||
|
int wrap;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Point3 Point3;
|
||||||
|
struct Point3
|
||||||
|
{
|
||||||
|
int x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Color Color;
|
||||||
|
struct Color
|
||||||
|
{
|
||||||
|
u8 r, g, b, a;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Vertex Vertex;
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
i32 x, y, z;
|
||||||
|
float q; // 1/z
|
||||||
|
u8 r, g, b, a;
|
||||||
|
u8 f; // fog
|
||||||
|
float s, t;
|
||||||
|
};
|
||||||
|
|
||||||
|
Canvas *makecanvas(int w, int h);
|
||||||
|
Texture *maketexture(int w, int h);
|
||||||
|
void putpixel(Canvas *canvas, Point3 p, Color c);
|
||||||
|
void clearcanvas(Canvas *canvas);
|
||||||
|
void drawTriangle(Canvas *canvas, Vertex p1, Vertex p2, Vertex p3);
|
||||||
|
|
||||||
|
// not good
|
||||||
|
void drawRect(Canvas *canvas, Point3 p1, Point3 p2, Color c);
|
||||||
|
void drawLine(Canvas *canvas, Point3 p1, Point3 p2, Color c);
|
||||||
|
|
||||||
|
//#define trace(...) printf(__VA_ARGS__)
|
||||||
|
#define trace(...)
|
||||||
|
|
||||||
|
|
||||||
|
int clamp(int x);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Render States
|
||||||
|
*/
|
||||||
|
enum TextureWrap {
|
||||||
|
WRAP_REPEAT,
|
||||||
|
WRAP_CLAMP,
|
||||||
|
WRAP_BORDER,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TextureFunction {
|
||||||
|
TFUNC_MODULATE,
|
||||||
|
TFUNC_DECAL,
|
||||||
|
TFUNC_HIGHLIGHT,
|
||||||
|
TFUNC_HIGHLIGHT2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AlphaTestFunc {
|
||||||
|
ALPHATEST_NEVER,
|
||||||
|
ALPHATEST_ALWAYS,
|
||||||
|
ALPHATEST_LESS,
|
||||||
|
ALPHATEST_LEQUAL,
|
||||||
|
ALPHATEST_EQUAL,
|
||||||
|
ALPHATEST_GEQUAL,
|
||||||
|
ALPHATEST_GREATER,
|
||||||
|
ALPHATEST_NOTEQUAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AlphaTestFail {
|
||||||
|
ALPHAFAIL_KEEP,
|
||||||
|
ALPHAFAIL_FB_ONLY,
|
||||||
|
ALPHAFAIL_ZB_ONLY,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DepthTestFunc {
|
||||||
|
DEPTHTEST_NEVER,
|
||||||
|
DEPTHTEST_ALWAYS,
|
||||||
|
DEPTHTEST_GEQUAL,
|
||||||
|
DEPTHTEST_GREATER,
|
||||||
|
};
|
||||||
|
|
||||||
|
// The blend equation is
|
||||||
|
// out = ((A - B) * C >> 7) + D
|
||||||
|
// A, B and D select the color, C the alpha value
|
||||||
|
enum AlphaBlendOp {
|
||||||
|
ALPHABLEND_SRC,
|
||||||
|
ALPHABLEND_DST,
|
||||||
|
ALPHABLEND_ZERO,
|
||||||
|
ALPHABLEND_FIX = ALPHABLEND_ZERO,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int srScissorX0, srScissorX1;
|
||||||
|
extern int srScissorY0, srScissorY1;
|
||||||
|
extern int srDepthTestEnable;
|
||||||
|
extern int srDepthTestFunction;
|
||||||
|
extern int srWriteZ;
|
||||||
|
extern int srAlphaTestEnable;
|
||||||
|
extern int srAlphaTestFunction;
|
||||||
|
extern int srAlphaTestReference;
|
||||||
|
extern int srAlphaTestFail;
|
||||||
|
extern int srAlphaBlendEnable;
|
||||||
|
extern int srAlphaBlendA;
|
||||||
|
extern int srAlphaBlendB;
|
||||||
|
extern int srAlphaBlendC;
|
||||||
|
extern int srAlphaBlendD;
|
||||||
|
extern int srAlphaBlendFix;
|
||||||
|
extern int srTexEnable;
|
||||||
|
extern Texture *srTexture;
|
||||||
|
extern int srWrapU;
|
||||||
|
extern int srWrapV;
|
||||||
|
extern Color srBorder;
|
||||||
|
extern int srTexUseAlpha;
|
||||||
|
extern int srTexFunc;
|
||||||
|
extern int srFogEnable;
|
||||||
|
extern Color srFogCol;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// end header
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define CEIL(p) (((p)+15) >> 4)
|
||||||
|
|
||||||
|
// render states
|
||||||
|
int srScissorX0, srScissorX1;
|
||||||
|
int srScissorY0, srScissorY1;
|
||||||
|
int srDepthTestEnable = 1;
|
||||||
|
int srDepthTestFunction = DEPTHTEST_GEQUAL;
|
||||||
|
int srWriteZ = 1;
|
||||||
|
int srAlphaTestEnable = 1;
|
||||||
|
int srAlphaTestFunction = ALPHATEST_ALWAYS;
|
||||||
|
int srAlphaTestReference;
|
||||||
|
int srAlphaTestFail = ALPHAFAIL_FB_ONLY;
|
||||||
|
int srAlphaBlendEnable = 1;
|
||||||
|
int srAlphaBlendA = ALPHABLEND_SRC;
|
||||||
|
int srAlphaBlendB = ALPHABLEND_DST;
|
||||||
|
int srAlphaBlendC = ALPHABLEND_SRC;
|
||||||
|
int srAlphaBlendD = ALPHABLEND_DST;
|
||||||
|
int srAlphaBlendFix = 0x80;
|
||||||
|
int srTexEnable = 0;
|
||||||
|
Texture *srTexture;
|
||||||
|
int srWrapU = WRAP_REPEAT;
|
||||||
|
int srWrapV = WRAP_REPEAT;
|
||||||
|
Color srBorder = { 255, 0, 0, 255 };
|
||||||
|
int srTexUseAlpha = 1;
|
||||||
|
int srTexFunc = TFUNC_MODULATE;
|
||||||
|
int srFogEnable = 0;
|
||||||
|
Color srFogCol = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
int clamp(int x) { if(x < 0) return 0; if(x > 255) return 255; return x; }
|
||||||
|
|
||||||
|
Canvas*
|
||||||
|
makecanvas(int w, int h)
|
||||||
|
{
|
||||||
|
Canvas *canv;
|
||||||
|
canv = (Canvas*)malloc(sizeof(*canv) + w*h*(4+4));
|
||||||
|
canv->w = w;
|
||||||
|
canv->h = h;
|
||||||
|
canv->fb = ((u8*)canv + sizeof(*canv));
|
||||||
|
canv->zbuf = (u32*)(canv->fb + w*h*4);
|
||||||
|
return canv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture*
|
||||||
|
maketexture(int w, int h)
|
||||||
|
{
|
||||||
|
Texture *t;
|
||||||
|
t = (Texture*)malloc(sizeof(*t) + w*h*4);
|
||||||
|
t->w = w;
|
||||||
|
t->h = h;
|
||||||
|
t->pixels = (u8*)t + sizeof(*t);
|
||||||
|
t->wrap = 0x11; // wrap u and v
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clearcanvas(Canvas *canvas)
|
||||||
|
{
|
||||||
|
memset(canvas->fb, 0, canvas->w*canvas->h*4);
|
||||||
|
memset(canvas->zbuf, 0, canvas->w*canvas->h*4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
writefb(Canvas *canvas, int x, int y, Color c)
|
||||||
|
{
|
||||||
|
u8 *px = &canvas->fb[(y*canvas->w + x)*4];
|
||||||
|
u32 *z = &canvas->zbuf[y*canvas->w + x];
|
||||||
|
|
||||||
|
px[3] = c.r;
|
||||||
|
px[2] = c.g;
|
||||||
|
px[1] = c.b;
|
||||||
|
px[0] = c.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
putpixel(Canvas *canvas, Point3 p, Color c)
|
||||||
|
{
|
||||||
|
// scissor test
|
||||||
|
if(p.x < srScissorX0 || p.x > srScissorX1 ||
|
||||||
|
p.y < srScissorY0 || p.y > srScissorY1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 *px = &canvas->fb[(p.y*canvas->w + p.x)*4];
|
||||||
|
u32 *z = &canvas->zbuf[p.y*canvas->w + p.x];
|
||||||
|
|
||||||
|
int fbwrite = 1;
|
||||||
|
int zbwrite = srWriteZ;
|
||||||
|
|
||||||
|
// alpha test
|
||||||
|
if(srAlphaTestEnable){
|
||||||
|
int fail;
|
||||||
|
switch(srAlphaTestFunction){
|
||||||
|
case ALPHATEST_NEVER:
|
||||||
|
fail = 1;
|
||||||
|
break;
|
||||||
|
case ALPHATEST_ALWAYS:
|
||||||
|
fail = 0;
|
||||||
|
break;
|
||||||
|
case ALPHATEST_LESS:
|
||||||
|
fail = c.a >= srAlphaTestReference;
|
||||||
|
break;
|
||||||
|
case ALPHATEST_LEQUAL:
|
||||||
|
fail = c.a > srAlphaTestReference;
|
||||||
|
break;
|
||||||
|
case ALPHATEST_EQUAL:
|
||||||
|
fail = c.a != srAlphaTestReference;
|
||||||
|
break;
|
||||||
|
case ALPHATEST_GEQUAL:
|
||||||
|
fail = c.a < srAlphaTestReference;
|
||||||
|
break;
|
||||||
|
case ALPHATEST_GREATER:
|
||||||
|
fail = c.a <= srAlphaTestReference;
|
||||||
|
break;
|
||||||
|
case ALPHATEST_NOTEQUAL:
|
||||||
|
fail = c.a == srAlphaTestReference;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(fail){
|
||||||
|
switch(srAlphaTestFail){
|
||||||
|
case ALPHAFAIL_KEEP:
|
||||||
|
return;
|
||||||
|
case ALPHAFAIL_FB_ONLY:
|
||||||
|
zbwrite = 0;
|
||||||
|
break;
|
||||||
|
case ALPHAFAIL_ZB_ONLY:
|
||||||
|
fbwrite = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ztest
|
||||||
|
if(srDepthTestEnable){
|
||||||
|
switch(srDepthTestFunction){
|
||||||
|
case DEPTHTEST_NEVER:
|
||||||
|
return;
|
||||||
|
case DEPTHTEST_ALWAYS:
|
||||||
|
break;
|
||||||
|
case DEPTHTEST_GEQUAL:
|
||||||
|
if(p.z < *z)
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case DEPTHTEST_GREATER:
|
||||||
|
if(p.z <= *z)
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color d = { px[3], px[2], px[1], px[0] };
|
||||||
|
|
||||||
|
// blend
|
||||||
|
if(srAlphaBlendEnable){
|
||||||
|
int ar, ag, ab;
|
||||||
|
int br, bg, bb;
|
||||||
|
int dr, dg, db;
|
||||||
|
int ca;
|
||||||
|
switch(srAlphaBlendA){
|
||||||
|
case ALPHABLEND_SRC:
|
||||||
|
ar = c.r;
|
||||||
|
ag = c.g;
|
||||||
|
ab = c.b;
|
||||||
|
break;
|
||||||
|
case ALPHABLEND_DST:
|
||||||
|
ar = d.r;
|
||||||
|
ag = d.g;
|
||||||
|
ab = d.b;
|
||||||
|
break;
|
||||||
|
case ALPHABLEND_ZERO:
|
||||||
|
ar = 0;
|
||||||
|
ag = 0;
|
||||||
|
ab = 0;
|
||||||
|
break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
switch(srAlphaBlendB){
|
||||||
|
case ALPHABLEND_SRC:
|
||||||
|
br = c.r;
|
||||||
|
bg = c.g;
|
||||||
|
bb = c.b;
|
||||||
|
break;
|
||||||
|
case ALPHABLEND_DST:
|
||||||
|
br = d.r;
|
||||||
|
bg = d.g;
|
||||||
|
bb = d.b;
|
||||||
|
break;
|
||||||
|
case ALPHABLEND_ZERO:
|
||||||
|
br = 0;
|
||||||
|
bg = 0;
|
||||||
|
bb = 0;
|
||||||
|
break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
switch(srAlphaBlendC){
|
||||||
|
case ALPHABLEND_SRC:
|
||||||
|
ca = c.a;
|
||||||
|
break;
|
||||||
|
case ALPHABLEND_DST:
|
||||||
|
ca = d.a;
|
||||||
|
break;
|
||||||
|
case ALPHABLEND_FIX:
|
||||||
|
ca = srAlphaBlendFix;
|
||||||
|
break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
switch(srAlphaBlendD){
|
||||||
|
case ALPHABLEND_SRC:
|
||||||
|
dr = c.r;
|
||||||
|
dg = c.g;
|
||||||
|
db = c.b;
|
||||||
|
break;
|
||||||
|
case ALPHABLEND_DST:
|
||||||
|
dr = d.r;
|
||||||
|
dg = d.g;
|
||||||
|
db = d.b;
|
||||||
|
break;
|
||||||
|
case ALPHABLEND_ZERO:
|
||||||
|
dr = 0;
|
||||||
|
dg = 0;
|
||||||
|
db = 0;
|
||||||
|
break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int r, g, b;
|
||||||
|
r = ((ar - br) * ca >> 7) + dr;
|
||||||
|
g = ((ag - bg) * ca >> 7) + dg;
|
||||||
|
b = ((ab - bb) * ca >> 7) + db;
|
||||||
|
|
||||||
|
c.r = clamp(r);
|
||||||
|
c.g = clamp(g);
|
||||||
|
c.b = clamp(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fbwrite)
|
||||||
|
writefb(canvas, p.x, p.y, c);
|
||||||
|
if(zbwrite)
|
||||||
|
*z = p.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color
|
||||||
|
sampletex_nearest(int u, int v)
|
||||||
|
{
|
||||||
|
Texture *tex = srTexture;
|
||||||
|
|
||||||
|
const int usize = tex->w;
|
||||||
|
const int vsize = tex->h;
|
||||||
|
|
||||||
|
int iu = u >> 4;
|
||||||
|
int iv = v >> 4;
|
||||||
|
|
||||||
|
switch(srWrapU){
|
||||||
|
case WRAP_REPEAT:
|
||||||
|
iu %= usize;
|
||||||
|
break;
|
||||||
|
case WRAP_CLAMP:
|
||||||
|
if(iu < 0) iu = 0;
|
||||||
|
if(iu >= usize) iu = usize-1;
|
||||||
|
break;
|
||||||
|
case WRAP_BORDER:
|
||||||
|
if(iu < 0 || iu >= usize)
|
||||||
|
return srBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(srWrapV){
|
||||||
|
case WRAP_REPEAT:
|
||||||
|
iv %= vsize;
|
||||||
|
break;
|
||||||
|
case WRAP_CLAMP:
|
||||||
|
if(iv < 0) iv = 0;
|
||||||
|
if(iv >= vsize) iv = vsize-1;
|
||||||
|
break;
|
||||||
|
case WRAP_BORDER:
|
||||||
|
if(iv < 0 || iv >= vsize)
|
||||||
|
return srBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *cp = &tex->pixels[(iv*tex->w + iu)*4];
|
||||||
|
Color c = { cp[0], cp[1], cp[2], cp[3] };
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// t is texture, f is fragment
|
||||||
|
Color
|
||||||
|
texfunc(Color t, Color f)
|
||||||
|
{
|
||||||
|
int r, g, b, a;
|
||||||
|
switch(srTexFunc){
|
||||||
|
case TFUNC_MODULATE:
|
||||||
|
r = t.r * f.r >> 7;
|
||||||
|
g = t.g * f.g >> 7;
|
||||||
|
b = t.b * f.b >> 7;
|
||||||
|
a = srTexUseAlpha ?
|
||||||
|
t.a * f.a >> 7 :
|
||||||
|
f.a;
|
||||||
|
break;
|
||||||
|
case TFUNC_DECAL:
|
||||||
|
r = t.r;
|
||||||
|
g = t.g;
|
||||||
|
b = t.b;
|
||||||
|
a = srTexUseAlpha ? t.a : f.a;
|
||||||
|
break;
|
||||||
|
case TFUNC_HIGHLIGHT:
|
||||||
|
r = (t.r * f.r >> 7) + f.a;
|
||||||
|
g = (t.g * f.g >> 7) + f.a;
|
||||||
|
b = (t.b * f.b >> 7) + f.a;
|
||||||
|
a = srTexUseAlpha ?
|
||||||
|
t.a + f.a :
|
||||||
|
f.a;
|
||||||
|
break;
|
||||||
|
case TFUNC_HIGHLIGHT2:
|
||||||
|
r = (t.r * f.r >> 7) + f.a;
|
||||||
|
g = (t.g * f.g >> 7) + f.a;
|
||||||
|
b = (t.b * f.b >> 7) + f.a;
|
||||||
|
a = srTexUseAlpha ? t.a : f.a;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
r = clamp(r);
|
||||||
|
g = clamp(g);
|
||||||
|
b = clamp(b);
|
||||||
|
a = clamp(a);
|
||||||
|
Color v = { r, g, b, a };
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point3 mkpnt(int x, int y, int z) { Point3 p = { x, y, z}; return p; }
|
||||||
|
|
||||||
|
void
|
||||||
|
drawRect(Canvas *canvas, Point3 p1, Point3 p2, Color c)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
for(y = p1.y; y <= p2.y; y++)
|
||||||
|
for(x = p1.x; x <= p2.x; x++)
|
||||||
|
putpixel(canvas, mkpnt(x, y, 0), c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drawLine(Canvas *canvas, Point3 p1, Point3 p2, Color c)
|
||||||
|
{
|
||||||
|
int dx, dy;
|
||||||
|
int incx, incy;
|
||||||
|
int e;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
dx = abs(p2.x-p1.x);
|
||||||
|
incx = p2.x > p1.x ? 1 : -1;
|
||||||
|
dy = abs(p2.y-p1.y);
|
||||||
|
incy = p2.y > p1.y ? 1 : -1;
|
||||||
|
e = 0;
|
||||||
|
if(dx == 0){
|
||||||
|
for(y = p1.y; y != p2.y; y += incy)
|
||||||
|
putpixel(canvas, mkpnt(p1.x, y, 0), c);
|
||||||
|
}else if(dx > dy){
|
||||||
|
y = p1.y;
|
||||||
|
for(x = p1.x; x != p2.x; x += incx){
|
||||||
|
putpixel(canvas, mkpnt(x, y, 0), c);
|
||||||
|
e += dy;
|
||||||
|
if(2*e >= dx){
|
||||||
|
e -= dx;
|
||||||
|
y += incy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
x = p1.x;
|
||||||
|
for(y = p1.y; y != p2.y; y += incy){
|
||||||
|
putpixel(canvas, mkpnt(x, y, 0), c);
|
||||||
|
e += dx;
|
||||||
|
if(2*e >= dy){
|
||||||
|
e -= dy;
|
||||||
|
x += incx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
attibutes we want to interpolate:
|
||||||
|
R G B A
|
||||||
|
U V / S T Q
|
||||||
|
X Y Z F
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct TriAttribs
|
||||||
|
{
|
||||||
|
i64 z;
|
||||||
|
i32 r, g, b, a;
|
||||||
|
i32 f;
|
||||||
|
float s, t;
|
||||||
|
float q;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
add1(struct TriAttribs *a, struct TriAttribs *b)
|
||||||
|
{
|
||||||
|
a->z += b->z;
|
||||||
|
a->r += b->r;
|
||||||
|
a->g += b->g;
|
||||||
|
a->b += b->b;
|
||||||
|
a->a += b->a;
|
||||||
|
a->f += b->f;
|
||||||
|
a->s += b->s;
|
||||||
|
a->t += b->t;
|
||||||
|
a->q += b->q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sub1(struct TriAttribs *a, struct TriAttribs *b)
|
||||||
|
{
|
||||||
|
a->z -= b->z;
|
||||||
|
a->r -= b->r;
|
||||||
|
a->g -= b->g;
|
||||||
|
a->b -= b->b;
|
||||||
|
a->a -= b->a;
|
||||||
|
a->f -= b->f;
|
||||||
|
a->s -= b->s;
|
||||||
|
a->t -= b->t;
|
||||||
|
a->q -= b->q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
guard(struct TriAttribs *a)
|
||||||
|
{
|
||||||
|
if(a->z < 0) a->z = 0;
|
||||||
|
else if(a->z > 0x3FFFFFFFC000LL) a->z = 0x3FFFFFFFC000LL;
|
||||||
|
if(a->r < 0) a->r = 0;
|
||||||
|
else if(a->r > 0xFF000) a->r = 0xFF000;
|
||||||
|
if(a->g < 0) a->g = 0;
|
||||||
|
else if(a->g > 0xFF000) a->g = 0xFF000;
|
||||||
|
if(a->b < 0) a->b = 0;
|
||||||
|
else if(a->b > 0xFF000) a->b = 0xFF000;
|
||||||
|
if(a->a < 0) a->a = 0;
|
||||||
|
else if(a->a > 0xFF000) a->a = 0xFF000;
|
||||||
|
if(a->f < 0) a->f = 0;
|
||||||
|
else if(a->f > 0xFF000) a->f = 0xFF000;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RasTri
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
int ymid, yend;
|
||||||
|
int right;
|
||||||
|
int e[2], dx[3], dy[3];
|
||||||
|
struct TriAttribs gx, gy, v, s;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
triangleSetup(struct RasTri *tri, Vertex v1, Vertex v2, Vertex v3)
|
||||||
|
{
|
||||||
|
int dx1, dx2, dx3;
|
||||||
|
int dy1, dy2, dy3;
|
||||||
|
|
||||||
|
dy1 = v3.y - v1.y; // long edge
|
||||||
|
if(dy1 == 0) return 1;
|
||||||
|
dx1 = v3.x - v1.x;
|
||||||
|
dx2 = v2.x - v1.x; // first small edge
|
||||||
|
dy2 = v2.y - v1.y;
|
||||||
|
dx3 = v3.x - v2.x; // second small edge
|
||||||
|
dy3 = v3.y - v2.y;
|
||||||
|
|
||||||
|
// this is twice the triangle area
|
||||||
|
const int area = dx2*dy1 - dx1*dy2;
|
||||||
|
if(area == 0) return 1;
|
||||||
|
// figure out if 0 or 1 is the right edge
|
||||||
|
tri->right = area < 0;
|
||||||
|
|
||||||
|
/* The gradients are to step whole pixels,
|
||||||
|
* so they are pre-multiplied by 16. */
|
||||||
|
|
||||||
|
float denom = 16.0f/area;
|
||||||
|
// gradients x
|
||||||
|
#define GX(p) ((v2.p - v1.p)*dy1 - (v3.p - v1.p)*dy2)
|
||||||
|
tri->gx.z = GX(z)*denom * 16384;
|
||||||
|
tri->gx.r = GX(r)*denom * 4096;
|
||||||
|
tri->gx.g = GX(g)*denom * 4096;
|
||||||
|
tri->gx.b = GX(b)*denom * 4096;
|
||||||
|
tri->gx.a = GX(a)*denom * 4096;
|
||||||
|
tri->gx.f = GX(f)*denom * 4096;
|
||||||
|
tri->gx.s = GX(s)*denom;
|
||||||
|
tri->gx.t = GX(t)*denom;
|
||||||
|
tri->gx.q = GX(q)*denom;
|
||||||
|
|
||||||
|
// gradients y
|
||||||
|
denom = -denom;
|
||||||
|
#define GY(p) ((v2.p - v1.p)*dx1 - (v3.p - v1.p)*dx2)
|
||||||
|
tri->gy.z = GY(z)*denom * 16384;
|
||||||
|
tri->gy.r = GY(r)*denom * 4096;
|
||||||
|
tri->gy.g = GY(g)*denom * 4096;
|
||||||
|
tri->gy.b = GY(b)*denom * 4096;
|
||||||
|
tri->gy.a = GY(a)*denom * 4096;
|
||||||
|
tri->gy.f = GY(f)*denom * 4096;
|
||||||
|
tri->gy.s = GY(s)*denom;
|
||||||
|
tri->gy.t = GY(t)*denom;
|
||||||
|
tri->gy.q = GY(q)*denom;
|
||||||
|
|
||||||
|
tri->ymid = CEIL(v2.y);
|
||||||
|
tri->yend = CEIL(v3.y);
|
||||||
|
|
||||||
|
tri->y = CEIL(v1.y);
|
||||||
|
tri->x = CEIL(v1.x);
|
||||||
|
|
||||||
|
tri->dy[0] = dy2<<4; // upper edge
|
||||||
|
tri->dy[1] = dy1<<4; // lower edge
|
||||||
|
tri->dy[2] = dy3<<4; // long edge
|
||||||
|
tri->dx[0] = dx2<<4;
|
||||||
|
tri->dx[1] = dx1<<4;
|
||||||
|
tri->dx[2] = dx3<<4;
|
||||||
|
|
||||||
|
// prestep to land on pixel center
|
||||||
|
|
||||||
|
int stepx = v1.x - (tri->x<<4);
|
||||||
|
int stepy = v1.y - (tri->y<<4);
|
||||||
|
tri->e[0] = (-stepy*tri->dx[0] + stepx*tri->dy[0]) >> 4;
|
||||||
|
tri->e[1] = (-stepy*tri->dx[1] + stepx*tri->dy[1]) >> 4;
|
||||||
|
|
||||||
|
// attributes along interpolated edge
|
||||||
|
// why is this cast needed? (mingw)
|
||||||
|
tri->v.z = (i64)v1.z*16384 - (stepy*tri->gy.z + stepx*tri->gx.z)/16;
|
||||||
|
tri->v.r = v1.r*4096 - (stepy*tri->gy.r + stepx*tri->gx.r)/16;
|
||||||
|
tri->v.g = v1.g*4096 - (stepy*tri->gy.g + stepx*tri->gx.g)/16;
|
||||||
|
tri->v.b = v1.b*4096 - (stepy*tri->gy.b + stepx*tri->gx.b)/16;
|
||||||
|
tri->v.a = v1.a*4096 - (stepy*tri->gy.a + stepx*tri->gx.a)/16;
|
||||||
|
tri->v.f = v1.f*4096 - (stepy*tri->gy.f + stepx*tri->gx.f)/16;
|
||||||
|
tri->v.s = v1.s - (stepy*tri->gy.s + stepx*tri->gx.s)/16.0f;
|
||||||
|
tri->v.t = v1.t - (stepy*tri->gy.t + stepx*tri->gx.t)/16.0f;
|
||||||
|
tri->v.q = v1.q - (stepy*tri->gy.q + stepx*tri->gx.q)/16.0f;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drawTriangle(Canvas *canvas, Vertex v1, Vertex v2, Vertex v3)
|
||||||
|
{
|
||||||
|
Color c;
|
||||||
|
struct RasTri tri;
|
||||||
|
int stepx, stepy;
|
||||||
|
|
||||||
|
// Sort such that we have from top to bottom v1,v2,v3
|
||||||
|
if(v2.y < v1.y){ Vertex tmp = v1; v1 = v2; v2 = tmp; }
|
||||||
|
if(v3.y < v1.y){ Vertex tmp = v1; v1 = v3; v3 = tmp; }
|
||||||
|
if(v3.y < v2.y){ Vertex tmp = v2; v2 = v3; v3 = tmp; }
|
||||||
|
|
||||||
|
if(triangleSetup(&tri, v1, v2, v3))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Current scanline start and end
|
||||||
|
int xn[2] = { tri.x, tri.x };
|
||||||
|
int a = !tri.right; // left edge
|
||||||
|
int b = tri.right; // right edge
|
||||||
|
|
||||||
|
// If upper triangle has no height, only do the lower part
|
||||||
|
if(tri.dy[0] == 0)
|
||||||
|
goto secondtri;
|
||||||
|
while(tri.y < tri.yend){
|
||||||
|
/* TODO: is this the righ way to step the edges? */
|
||||||
|
|
||||||
|
/* Step x and interpolated value down left edge */
|
||||||
|
while(tri.e[a] <= -tri.dy[a]){
|
||||||
|
xn[a]--;
|
||||||
|
tri.e[a] += tri.dy[a];
|
||||||
|
sub1(&tri.v, &tri.gx);
|
||||||
|
}
|
||||||
|
while(tri.e[a] > 0){
|
||||||
|
xn[a]++;
|
||||||
|
tri.e[a] -= tri.dy[a];
|
||||||
|
add1(&tri.v, &tri.gx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step x down right edge */
|
||||||
|
while(tri.e[b] <= -tri.dy[b]){
|
||||||
|
xn[b]--;
|
||||||
|
tri.e[b] += tri.dy[b];
|
||||||
|
}
|
||||||
|
while(tri.e[b] > 0){
|
||||||
|
xn[b]++;
|
||||||
|
tri.e[b] -= tri.dy[b];
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we reach the mid vertex, change state and jump to start of loop again
|
||||||
|
// TODO: this is a bit ugly in here...can we fix it?
|
||||||
|
if(tri.y == tri.ymid){
|
||||||
|
secondtri:
|
||||||
|
tri.dx[0] = tri.dx[2];
|
||||||
|
tri.dy[0] = tri.dy[2];
|
||||||
|
// Either the while prevents this or we returned early because dy1 == 0
|
||||||
|
assert(tri.dy[0] != 0);
|
||||||
|
stepx = v2.x - (xn[0]<<4);
|
||||||
|
stepy = v2.y - (tri.y<<4);
|
||||||
|
tri.e[0] = (-stepy*tri.dx[0] + stepx*tri.dy[0]) >> 4;
|
||||||
|
|
||||||
|
tri.ymid = -1; // so we don't do this again
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rasterize one line */
|
||||||
|
tri.s = tri.v;
|
||||||
|
for(tri.x = xn[a]; tri.x < xn[b]; tri.x++){
|
||||||
|
guard(&tri.s);
|
||||||
|
c.r = tri.s.r >> 12;
|
||||||
|
c.g = tri.s.g >> 12;
|
||||||
|
c.b = tri.s.b >> 12;
|
||||||
|
c.a = tri.s.a >> 12;
|
||||||
|
if(srTexEnable && srTexture){
|
||||||
|
float w = 1.0f/tri.s.q;
|
||||||
|
float s = tri.s.s * w;
|
||||||
|
float t = tri.s.t * w;
|
||||||
|
int u = s * srTexture->w * 16;
|
||||||
|
int v = t * srTexture->h * 16;
|
||||||
|
Color texc = sampletex_nearest(u, v);
|
||||||
|
c = texfunc(texc, c);
|
||||||
|
}
|
||||||
|
if(srFogEnable){
|
||||||
|
const int f = tri.s.f >> 12;
|
||||||
|
c.r = (f*c.r >> 8) + ((255 - f)*srFogCol.r >> 8);
|
||||||
|
c.g = (f*c.g >> 8) + ((255 - f)*srFogCol.g >> 8);
|
||||||
|
c.b = (f*c.b >> 8) + ((255 - f)*srFogCol.b >> 8);
|
||||||
|
}
|
||||||
|
putpixel(canvas, mkpnt(tri.x, tri.y, tri.s.z>>14), c);
|
||||||
|
add1(&tri.s, &tri.gx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step in y */
|
||||||
|
tri.y++;
|
||||||
|
tri.e[a] += tri.dx[a];
|
||||||
|
tri.e[b] += tri.dx[b];
|
||||||
|
add1(&tri.v, &tri.gy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas *canvas;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace rw;
|
||||||
|
|
||||||
|
void
|
||||||
|
rastest_renderTriangles(RWDEVICE::Im2DVertex *scrverts, int32 numVerts, uint16 *indices, int32 numTris)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
RGBA col;
|
||||||
|
rs::Vertex v[3];
|
||||||
|
RWDEVICE::Im2DVertex *iv;
|
||||||
|
|
||||||
|
rs::srDepthTestEnable = 1;
|
||||||
|
rs::srAlphaTestEnable = 0;
|
||||||
|
rs::srTexEnable = 0;
|
||||||
|
rs::srAlphaBlendEnable = 0;
|
||||||
|
|
||||||
|
while(numTris--){
|
||||||
|
for(i = 0; i < 3; i++){
|
||||||
|
iv = &scrverts[indices[i]];
|
||||||
|
v[i].x = iv->x * 16.0f;
|
||||||
|
v[i].y = iv->y * 16.0f;
|
||||||
|
v[i].z = 16777216*(1.0f-iv->z);
|
||||||
|
v[i].q = iv->w;
|
||||||
|
col = iv->getColor();
|
||||||
|
v[i].r = col.red;
|
||||||
|
v[i].g = col.green;
|
||||||
|
v[i].b = col.blue;
|
||||||
|
v[i].a = col.alpha;
|
||||||
|
v[i].f = 0;
|
||||||
|
v[i].s = iv->u*iv->w;
|
||||||
|
v[i].t = iv->v*iv->w;
|
||||||
|
}
|
||||||
|
drawTriangle(rs::canvas, v[0], v[1], v[2]);
|
||||||
|
|
||||||
|
indices += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern rw::Raster *testras;
|
||||||
|
|
||||||
|
void
|
||||||
|
beginSoftras(void)
|
||||||
|
{
|
||||||
|
Camera *cam = (Camera*)engine->currentCamera;
|
||||||
|
|
||||||
|
if(rs::canvas == nil ||
|
||||||
|
cam->frameBuffer->width != rs::canvas->w ||
|
||||||
|
cam->frameBuffer->height != rs::canvas->h){
|
||||||
|
rs::canvas = rs::makecanvas(cam->frameBuffer->width, cam->frameBuffer->height);
|
||||||
|
testras = rw::Raster::create(rs::canvas->w, rs::canvas->h, 32, rw::Raster::C8888);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearcanvas(rs::canvas);
|
||||||
|
rs::srScissorX0 = 0;
|
||||||
|
rs::srScissorX1 = rs::canvas->w-1;
|
||||||
|
rs::srScissorY0 = 0;
|
||||||
|
rs::srScissorY1 = rs::canvas->h-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
endSoftras(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8 *dst = testras->lock(0);
|
||||||
|
uint8 *src = rs::canvas->fb;
|
||||||
|
for(i = 0; i < rs::canvas->w*rs::canvas->h; i++){
|
||||||
|
dst[0] = src[1];
|
||||||
|
dst[1] = src[2];
|
||||||
|
dst[2] = src[3];
|
||||||
|
dst[3] = src[0];
|
||||||
|
dst += 4;
|
||||||
|
src += 4;
|
||||||
|
}
|
||||||
|
// abgr in canvas
|
||||||
|
// bgra in raster
|
||||||
|
testras->unlock(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct PixVert PixVert;
|
||||||
|
struct PixVert
|
||||||
|
{
|
||||||
|
float x, y, z, q;
|
||||||
|
int r, g, b, a;
|
||||||
|
float u, v;
|
||||||
|
};
|
||||||
|
#include "test.inc"
|
||||||
|
|
||||||
|
void
|
||||||
|
drawtest(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
rs::Vertex v[3];
|
||||||
|
|
||||||
|
rs::srDepthTestEnable = 1;
|
||||||
|
rs::srAlphaTestEnable = 0;
|
||||||
|
rs::srTexEnable = 0;
|
||||||
|
rs::srAlphaBlendEnable = 0;
|
||||||
|
|
||||||
|
for(i = 0; i < nelem(verts); i += 3){
|
||||||
|
for(j = 0; j < 3; j++){
|
||||||
|
v[j].x = verts[i+j].x * 16.0f;
|
||||||
|
v[j].y = verts[i+j].y * 16.0f;
|
||||||
|
v[j].z = 16777216*(1.0f - verts[i+j].z);
|
||||||
|
v[j].q = verts[i+j].q;
|
||||||
|
v[j].r = verts[i+j].r;
|
||||||
|
v[j].g = verts[i+j].g;
|
||||||
|
v[j].b = verts[i+j].b;
|
||||||
|
v[j].a = verts[i+j].a;
|
||||||
|
v[j].f = 0;
|
||||||
|
v[j].s = verts[i+j].u*v[j].q;
|
||||||
|
v[j].t = verts[i+j].v*v[j].q;
|
||||||
|
}
|
||||||
|
drawTriangle(rs::canvas, v[0], v[1], v[2]);
|
||||||
|
}
|
||||||
|
//exit(0);
|
||||||
|
}
|
||||||
|
*/
|
@ -1,200 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
661
tools/clumpview/tl_tests.cpp
Normal file
661
tools/clumpview/tl_tests.cpp
Normal file
@ -0,0 +1,661 @@
|
|||||||
|
#include <rw.h>
|
||||||
|
#include <skeleton.h>
|
||||||
|
|
||||||
|
extern bool dosoftras;
|
||||||
|
|
||||||
|
using namespace rw;
|
||||||
|
using namespace RWDEVICE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is a test to implement T&L in software and render with Im2D
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace gen {
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ObjSpace3DVertex
|
||||||
|
{
|
||||||
|
V3d objVertex;
|
||||||
|
V3d objNormal;
|
||||||
|
RGBA color;
|
||||||
|
TexCoords texCoords;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CLIPXLO = 0x01,
|
||||||
|
CLIPXHI = 0x02,
|
||||||
|
CLIPX = 0x03,
|
||||||
|
CLIPYLO = 0x04,
|
||||||
|
CLIPYHI = 0x08,
|
||||||
|
CLIPY = 0x0C,
|
||||||
|
CLIPZLO = 0x10,
|
||||||
|
CLIPZHI = 0x20,
|
||||||
|
CLIPZ = 0x30,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CamSpace3DVertex
|
||||||
|
{
|
||||||
|
V3d camVertex;
|
||||||
|
uint8 clipFlags;
|
||||||
|
RGBAf color;
|
||||||
|
TexCoords texCoords;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InstanceData
|
||||||
|
{
|
||||||
|
uint16 *indices;
|
||||||
|
int32 numIndices;
|
||||||
|
ObjSpace3DVertex *vertices;
|
||||||
|
int32 numVertices;
|
||||||
|
// int vertStride; // not really needed right now
|
||||||
|
Material *material;
|
||||||
|
Mesh *mesh;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InstanceDataHeader : public rw::InstanceDataHeader
|
||||||
|
{
|
||||||
|
uint32 serialNumber;
|
||||||
|
ObjSpace3DVertex *vertices;
|
||||||
|
uint16 *indices;
|
||||||
|
InstanceData *inst;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
instanceAtomic(Atomic *atomic)
|
||||||
|
{
|
||||||
|
static V3d zeroNorm = { 0.0f, 0.0f, 0.0f };
|
||||||
|
static RGBA black = { 0, 0, 0, 255 };
|
||||||
|
static TexCoords zeroTex = { 0.0f, 0.0f };
|
||||||
|
int i;
|
||||||
|
uint j;
|
||||||
|
int x, x1, x2, x3;
|
||||||
|
Geometry *geo;
|
||||||
|
MeshHeader *header;
|
||||||
|
Mesh *mesh;
|
||||||
|
InstanceDataHeader *insthead;
|
||||||
|
InstanceData *inst;
|
||||||
|
uint32 firstVert;
|
||||||
|
uint16 *srcindices, *dstindices;
|
||||||
|
|
||||||
|
geo = atomic->geometry;
|
||||||
|
if(geo->instData)
|
||||||
|
return;
|
||||||
|
header = geo->meshHeader;
|
||||||
|
int numTris;
|
||||||
|
if(header->flags & MeshHeader::TRISTRIP)
|
||||||
|
numTris = header->totalIndices - 2*header->numMeshes;
|
||||||
|
else
|
||||||
|
numTris = header->totalIndices / 3;
|
||||||
|
int size;
|
||||||
|
size = sizeof(InstanceDataHeader) + header->numMeshes*sizeof(InstanceData) +
|
||||||
|
geo->numVertices*sizeof(ObjSpace3DVertex) + numTris*6*sizeof(uint16);
|
||||||
|
insthead = (InstanceDataHeader*)rwNew(size, ID_GEOMETRY);
|
||||||
|
geo->instData = insthead;
|
||||||
|
insthead->platform = 0;
|
||||||
|
insthead->serialNumber = header->serialNum;
|
||||||
|
inst = (InstanceData*)(insthead+1);
|
||||||
|
insthead->inst = inst;
|
||||||
|
insthead->vertices = (ObjSpace3DVertex*)(inst+header->numMeshes);
|
||||||
|
dstindices = (uint16*)(insthead->vertices+geo->numVertices);
|
||||||
|
insthead->indices = dstindices;
|
||||||
|
|
||||||
|
// TODO: morphing
|
||||||
|
MorphTarget *mt = geo->morphTargets;
|
||||||
|
for(i = 0; i < geo->numVertices; i++){
|
||||||
|
insthead->vertices[i].objVertex = mt->vertices[i];
|
||||||
|
if(geo->flags & Geometry::NORMALS)
|
||||||
|
insthead->vertices[i].objNormal = mt->normals[i];
|
||||||
|
else
|
||||||
|
insthead->vertices[i].objNormal = zeroNorm;
|
||||||
|
if(geo->flags & Geometry::PRELIT)
|
||||||
|
insthead->vertices[i].color = geo->colors[i];
|
||||||
|
else
|
||||||
|
insthead->vertices[i].color = black;
|
||||||
|
if(geo->numTexCoordSets > 0)
|
||||||
|
insthead->vertices[i].texCoords = geo->texCoords[0][i];
|
||||||
|
else
|
||||||
|
insthead->vertices[i].texCoords = zeroTex;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh = header->getMeshes();
|
||||||
|
for(i = 0; i < header->numMeshes; i++){
|
||||||
|
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
|
||||||
|
&firstVert, &inst->numVertices);
|
||||||
|
inst->indices = dstindices;
|
||||||
|
inst->vertices = &insthead->vertices[firstVert];
|
||||||
|
inst->mesh = mesh;
|
||||||
|
inst->material = mesh->material;
|
||||||
|
srcindices = mesh->indices;
|
||||||
|
if(header->flags & MeshHeader::TRISTRIP){
|
||||||
|
inst->numIndices = 0;
|
||||||
|
x = 0;
|
||||||
|
for(j = 0; j < mesh->numIndices-2; j++){
|
||||||
|
x1 = srcindices[j+x];
|
||||||
|
x ^= 1;
|
||||||
|
x2 = srcindices[j+x];
|
||||||
|
x3 = srcindices[j+2];
|
||||||
|
if(x1 != x2 && x2 != x3 && x1 != x3){
|
||||||
|
dstindices[0] = x1;
|
||||||
|
dstindices[1] = x2;
|
||||||
|
dstindices[2] = x3;
|
||||||
|
dstindices += 3;
|
||||||
|
inst->numIndices += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
inst->numIndices = mesh->numIndices;
|
||||||
|
for(j = 0; j < mesh->numIndices; j += 3){
|
||||||
|
dstindices[0] = srcindices[j+0] - firstVert;
|
||||||
|
dstindices[1] = srcindices[j+1] - firstVert;
|
||||||
|
dstindices[2] = srcindices[j+2] - firstVert;
|
||||||
|
dstindices += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inst++;
|
||||||
|
mesh++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MeshState
|
||||||
|
{
|
||||||
|
int32 flags;
|
||||||
|
Matrix obj2cam;
|
||||||
|
Matrix obj2world;
|
||||||
|
int32 numVertices;
|
||||||
|
int32 numPrimitives;
|
||||||
|
SurfaceProperties surfProps;
|
||||||
|
RGBA matCol;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
cam2screen(Im2DVertex *scrvert, CamSpace3DVertex *camvert)
|
||||||
|
{
|
||||||
|
RGBA col;
|
||||||
|
float32 recipZ;
|
||||||
|
Camera *cam = (Camera*)engine->currentCamera;
|
||||||
|
int32 width = cam->frameBuffer->width;
|
||||||
|
int32 height = cam->frameBuffer->height;
|
||||||
|
recipZ = 1.0f/camvert->camVertex.z;
|
||||||
|
|
||||||
|
scrvert->setScreenX(camvert->camVertex.x * recipZ * width);
|
||||||
|
scrvert->setScreenY(camvert->camVertex.y * recipZ * height);
|
||||||
|
// scrvert->setScreenX(camvert->camVertex.x * recipZ * width/2 + width/4);
|
||||||
|
// scrvert->setScreenY(camvert->camVertex.y * recipZ * height/2 + height/4);
|
||||||
|
scrvert->setScreenZ(recipZ * cam->zScale + cam->zShift);
|
||||||
|
scrvert->setCameraZ(camvert->camVertex.z);
|
||||||
|
scrvert->setRecipCameraZ(recipZ);
|
||||||
|
scrvert->setU(camvert->texCoords.u, recipZ);
|
||||||
|
scrvert->setV(camvert->texCoords.v, recipZ);
|
||||||
|
convColor(&col, &camvert->color);
|
||||||
|
scrvert->setColor(col.red, col.green, col.blue, col.alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
transform(MeshState *mstate, ObjSpace3DVertex *objverts, CamSpace3DVertex *camverts, Im2DVertex *scrverts)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
float32 z;
|
||||||
|
Camera *cam = (Camera*)engine->currentCamera;
|
||||||
|
|
||||||
|
for(i = 0; i < mstate->numVertices; i++){
|
||||||
|
V3d::transformPoints(&camverts[i].camVertex, &objverts[i].objVertex, 1, &mstate->obj2cam);
|
||||||
|
convColor(&camverts[i].color, &objverts[i].color);
|
||||||
|
camverts[i].texCoords = objverts[i].texCoords;
|
||||||
|
|
||||||
|
camverts[i].clipFlags = 0;
|
||||||
|
z = camverts[i].camVertex.z;
|
||||||
|
// 0 < x < z
|
||||||
|
if(camverts[i].camVertex.x >= z) camverts[i].clipFlags |= CLIPXHI;
|
||||||
|
if(camverts[i].camVertex.x <= 0) camverts[i].clipFlags |= CLIPXLO;
|
||||||
|
// 0 < y < z
|
||||||
|
if(camverts[i].camVertex.y >= z) camverts[i].clipFlags |= CLIPYHI;
|
||||||
|
if(camverts[i].camVertex.y <= 0) camverts[i].clipFlags |= CLIPYLO;
|
||||||
|
// near < z < far
|
||||||
|
if(z >= cam->farPlane) camverts[i].clipFlags |= CLIPZHI;
|
||||||
|
if(z <= cam->nearPlane) camverts[i].clipFlags |= CLIPZLO;
|
||||||
|
|
||||||
|
cam2screen(&scrverts[i], &camverts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
light(MeshState *mstate, ObjSpace3DVertex *objverts, CamSpace3DVertex *camverts)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
RGBAf colf;
|
||||||
|
RGBAf amb = ambLight;
|
||||||
|
amb = scale(ambLight, mstate->surfProps.ambient);
|
||||||
|
for(i = 0; i < mstate->numVertices; i++){
|
||||||
|
camverts[i].color = add(camverts[i].color, amb);
|
||||||
|
if((mstate->flags & Geometry::NORMALS) == 0)
|
||||||
|
continue;
|
||||||
|
for(int32 k = 0; k < numDirectionals; k++){
|
||||||
|
float32 f = dot(objverts[i].objNormal, neg(directionals[k].at));
|
||||||
|
if(f <= 0.0f) continue;
|
||||||
|
f *= mstate->surfProps.diffuse;
|
||||||
|
colf = scale(directionals[k].color, f);
|
||||||
|
camverts[i].color = add(camverts[i].color, colf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
postlight(MeshState *mstate, CamSpace3DVertex *camverts, Im2DVertex *scrverts)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
RGBA col;
|
||||||
|
RGBAf colf;
|
||||||
|
for(i = 0; i < mstate->numVertices; i++){
|
||||||
|
convColor(&colf, &mstate->matCol);
|
||||||
|
camverts[i].color = modulate(camverts[i].color, colf);
|
||||||
|
clamp(&camverts[i].color);
|
||||||
|
convColor(&col, &camverts[i].color);
|
||||||
|
scrverts[i].setColor(col.red, col.green, col.blue, col.alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32
|
||||||
|
cullTriangles(MeshState *mstate, CamSpace3DVertex *camverts, uint16 *indices, uint16 *clipindices)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
int32 x1, x2, x3;
|
||||||
|
int32 newNumPrims;
|
||||||
|
int32 numClip;
|
||||||
|
|
||||||
|
newNumPrims = 0;
|
||||||
|
numClip = 0;
|
||||||
|
for(i = 0; i < mstate->numPrimitives; i++, indices += 3){
|
||||||
|
x1 = indices[0];
|
||||||
|
x2 = indices[1];
|
||||||
|
x3 = indices[2];
|
||||||
|
// Only a simple frustum call
|
||||||
|
if(camverts[x1].clipFlags &
|
||||||
|
camverts[x2].clipFlags &
|
||||||
|
camverts[x3].clipFlags)
|
||||||
|
continue;
|
||||||
|
if(camverts[x1].clipFlags |
|
||||||
|
camverts[x2].clipFlags |
|
||||||
|
camverts[x3].clipFlags)
|
||||||
|
numClip++;
|
||||||
|
// The Triangle is in, probably
|
||||||
|
clipindices[0] = x1;
|
||||||
|
clipindices[1] = x2;
|
||||||
|
clipindices[2] = x3;
|
||||||
|
clipindices += 3;
|
||||||
|
newNumPrims++;
|
||||||
|
}
|
||||||
|
mstate->numPrimitives = newNumPrims;
|
||||||
|
return numClip;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
interpVertex(CamSpace3DVertex *out, CamSpace3DVertex *v1, CamSpace3DVertex *v2, float32 t)
|
||||||
|
{
|
||||||
|
float32 z;
|
||||||
|
float32 invt;
|
||||||
|
Camera *cam = (Camera*)engine->currentCamera;
|
||||||
|
|
||||||
|
invt = 1.0f - t;
|
||||||
|
out->camVertex = add(scale(v1->camVertex, invt), scale(v2->camVertex, t));
|
||||||
|
out->color = add(scale(v1->color, invt), scale(v2->color, t));
|
||||||
|
out->texCoords.u = v1->texCoords.u*invt + v2->texCoords.u*t;
|
||||||
|
out->texCoords.v = v1->texCoords.v*invt + v2->texCoords.v*t;
|
||||||
|
|
||||||
|
out->clipFlags = 0;
|
||||||
|
z = out->camVertex.z;
|
||||||
|
// 0 < x < z
|
||||||
|
if(out->camVertex.x >= z) out->clipFlags |= CLIPXHI;
|
||||||
|
if(out->camVertex.x <= 0) out->clipFlags |= CLIPXLO;
|
||||||
|
// 0 < y < z
|
||||||
|
if(out->camVertex.y >= z) out->clipFlags |= CLIPYHI;
|
||||||
|
if(out->camVertex.y <= 0) out->clipFlags |= CLIPYLO;
|
||||||
|
// near < z < far
|
||||||
|
if(z >= cam->farPlane) out->clipFlags |= CLIPZHI;
|
||||||
|
if(z <= cam->nearPlane) out->clipFlags |= CLIPZLO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clipTriangles(MeshState *mstate, CamSpace3DVertex *camverts, Im2DVertex *scrverts, uint16 *indices, uint16 *clipindices)
|
||||||
|
{
|
||||||
|
int32 i, j;
|
||||||
|
int32 x1, x2, x3;
|
||||||
|
int32 newNumPrims;
|
||||||
|
CamSpace3DVertex buf[18];
|
||||||
|
CamSpace3DVertex *in, *out, *tmp;
|
||||||
|
int32 nin, nout;
|
||||||
|
float32 t;
|
||||||
|
Camera *cam = (Camera*)engine->currentCamera;
|
||||||
|
|
||||||
|
newNumPrims = 0;
|
||||||
|
for(i = 0; i < mstate->numPrimitives; i++, indices += 3){
|
||||||
|
x1 = indices[0];
|
||||||
|
x2 = indices[1];
|
||||||
|
x3 = indices[2];
|
||||||
|
|
||||||
|
if((camverts[x1].clipFlags |
|
||||||
|
camverts[x2].clipFlags |
|
||||||
|
camverts[x3].clipFlags) == 0){
|
||||||
|
// all inside
|
||||||
|
clipindices[0] = x1;
|
||||||
|
clipindices[1] = x2;
|
||||||
|
clipindices[2] = x3;
|
||||||
|
clipindices += 3;
|
||||||
|
newNumPrims++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up triangle
|
||||||
|
in = &buf[0];
|
||||||
|
out = &buf[9];
|
||||||
|
in[0] = camverts[x1];
|
||||||
|
in[1] = camverts[x2];
|
||||||
|
in[2] = camverts[x3];
|
||||||
|
nin = 3;
|
||||||
|
nout = 0;
|
||||||
|
|
||||||
|
#define V(a) in[a].camVertex.
|
||||||
|
|
||||||
|
// clip z near
|
||||||
|
for(j = 0; j < nin; j++){
|
||||||
|
x1 = j;
|
||||||
|
x2 = (j+1) % nin;
|
||||||
|
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPZLO){
|
||||||
|
t = (cam->nearPlane - V(x1)z)/(V(x2)z - V(x1)z);
|
||||||
|
interpVertex(&out[nout++], &in[x1], &in[x2], t);
|
||||||
|
}
|
||||||
|
if((in[x2].clipFlags & CLIPZLO) == 0)
|
||||||
|
out[nout++] = in[x2];
|
||||||
|
}
|
||||||
|
// clip z far
|
||||||
|
nin = nout; nout = 0;
|
||||||
|
tmp = in; in = out; out = tmp;
|
||||||
|
for(j = 0; j < nin; j++){
|
||||||
|
x1 = j;
|
||||||
|
x2 = (j+1) % nin;
|
||||||
|
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPZHI){
|
||||||
|
t = (cam->farPlane - V(x1)z)/(V(x2)z - V(x1)z);
|
||||||
|
interpVertex(&out[nout++], &in[x1], &in[x2], t);
|
||||||
|
}
|
||||||
|
if((in[x2].clipFlags & CLIPZHI) == 0)
|
||||||
|
out[nout++] = in[x2];
|
||||||
|
}
|
||||||
|
// clip y 0
|
||||||
|
nin = nout; nout = 0;
|
||||||
|
tmp = in; in = out; out = tmp;
|
||||||
|
for(j = 0; j < nin; j++){
|
||||||
|
x1 = j;
|
||||||
|
x2 = (j+1) % nin;
|
||||||
|
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPYLO){
|
||||||
|
t = -V(x1)y/(V(x2)y - V(x1)y);
|
||||||
|
interpVertex(&out[nout++], &in[x1], &in[x2], t);
|
||||||
|
}
|
||||||
|
if((in[x2].clipFlags & CLIPYLO) == 0)
|
||||||
|
out[nout++] = in[x2];
|
||||||
|
}
|
||||||
|
// clip y z
|
||||||
|
nin = nout; nout = 0;
|
||||||
|
tmp = in; in = out; out = tmp;
|
||||||
|
for(j = 0; j < nin; j++){
|
||||||
|
x1 = j;
|
||||||
|
x2 = (j+1) % nin;
|
||||||
|
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPYHI){
|
||||||
|
t = (V(x1)z - V(x1)y)/(V(x1)z - V(x1)y + V(x2)y - V(x2)z);
|
||||||
|
interpVertex(&out[nout++], &in[x1], &in[x2], t);
|
||||||
|
}
|
||||||
|
if((in[x2].clipFlags & CLIPYHI) == 0)
|
||||||
|
out[nout++] = in[x2];
|
||||||
|
}
|
||||||
|
// clip x 0
|
||||||
|
nin = nout; nout = 0;
|
||||||
|
tmp = in; in = out; out = tmp;
|
||||||
|
for(j = 0; j < nin; j++){
|
||||||
|
x1 = j;
|
||||||
|
x2 = (j+1) % nin;
|
||||||
|
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPXLO){
|
||||||
|
t = -V(x1)x/(V(x2)x - V(x1)x);
|
||||||
|
interpVertex(&out[nout++], &in[x1], &in[x2], t);
|
||||||
|
}
|
||||||
|
if((in[x2].clipFlags & CLIPXLO) == 0)
|
||||||
|
out[nout++] = in[x2];
|
||||||
|
}
|
||||||
|
// clip x z
|
||||||
|
nin = nout; nout = 0;
|
||||||
|
tmp = in; in = out; out = tmp;
|
||||||
|
for(j = 0; j < nin; j++){
|
||||||
|
x1 = j;
|
||||||
|
x2 = (j+1) % nin;
|
||||||
|
if((in[x1].clipFlags ^ in[x2].clipFlags) & CLIPXHI){
|
||||||
|
t = (V(x1)z - V(x1)x)/(V(x1)z - V(x1)x + V(x2)x - V(x2)z);
|
||||||
|
interpVertex(&out[nout++], &in[x1], &in[x2], t);
|
||||||
|
}
|
||||||
|
if((in[x2].clipFlags & CLIPXHI) == 0)
|
||||||
|
out[nout++] = in[x2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert new triangles
|
||||||
|
x1 = mstate->numVertices;
|
||||||
|
for(j = 0; j < nout; j++){
|
||||||
|
x2 = mstate->numVertices++;
|
||||||
|
camverts[x2] = out[j];
|
||||||
|
cam2screen(&scrverts[x2], &camverts[x2]);
|
||||||
|
}
|
||||||
|
x2 = x1+1;
|
||||||
|
for(j = 0; j < nout-2; j++){
|
||||||
|
clipindices[0] = x1;
|
||||||
|
clipindices[1] = x2++;
|
||||||
|
clipindices[2] = x2;
|
||||||
|
clipindices += 3;
|
||||||
|
newNumPrims++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mstate->numPrimitives = newNumPrims;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
submitTriangles(RWDEVICE::Im2DVertex *scrverts, int32 numVerts, uint16 *indices, int32 numTris)
|
||||||
|
{
|
||||||
|
void rastest_renderTriangles(RWDEVICE::Im2DVertex *scrverts, int32 verts, uint16 *indices, int32 numTris);
|
||||||
|
rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
|
||||||
|
if(dosoftras)
|
||||||
|
rastest_renderTriangles(scrverts, numVerts, indices, numTris);
|
||||||
|
else{
|
||||||
|
//int i;
|
||||||
|
//for(i = 0; i < numVerts; i++){
|
||||||
|
// scrverts[i].x = (int)(scrverts[i].x*16.0f) / 16.0f;
|
||||||
|
// scrverts[i].y = (int)(scrverts[i].y*16.0f) / 16.0f;
|
||||||
|
//}
|
||||||
|
im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, scrverts, numVerts,
|
||||||
|
indices, numTris*3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
drawMesh(MeshState *mstate, ObjSpace3DVertex *objverts, uint16 *indices)
|
||||||
|
{
|
||||||
|
CamSpace3DVertex *camverts;
|
||||||
|
Im2DVertex *scrverts;
|
||||||
|
uint16 *cullindices, *clipindices;
|
||||||
|
uint32 numClip;
|
||||||
|
|
||||||
|
camverts = rwNewT(CamSpace3DVertex, mstate->numVertices, MEMDUR_FUNCTION);
|
||||||
|
scrverts = rwNewT(Im2DVertex, mstate->numVertices, MEMDUR_FUNCTION);
|
||||||
|
cullindices = rwNewT(uint16, mstate->numPrimitives*3, MEMDUR_FUNCTION);
|
||||||
|
|
||||||
|
transform(mstate, objverts, camverts, scrverts);
|
||||||
|
|
||||||
|
numClip = cullTriangles(mstate, camverts, indices, cullindices);
|
||||||
|
|
||||||
|
// int32 i;
|
||||||
|
// for(i = 0; i < mstate->numVertices; i++){
|
||||||
|
// if(camverts[i].clipFlags & CLIPX)
|
||||||
|
// camverts[i].color.red = 255;
|
||||||
|
// if(camverts[i].clipFlags & CLIPY)
|
||||||
|
// camverts[i].color.green = 255;
|
||||||
|
// if(camverts[i].clipFlags & CLIPZ)
|
||||||
|
// camverts[i].color.blue = 255;
|
||||||
|
// }
|
||||||
|
|
||||||
|
light(mstate, objverts, camverts);
|
||||||
|
|
||||||
|
// mstate->matCol.red = 255;
|
||||||
|
// mstate->matCol.green = 255;
|
||||||
|
// mstate->matCol.blue = 255;
|
||||||
|
|
||||||
|
postlight(mstate, camverts, scrverts);
|
||||||
|
|
||||||
|
// each triangle can have a maximum of 9 vertices (7 triangles) after clipping
|
||||||
|
// so resize to whatever we may need
|
||||||
|
camverts = rwResizeT(CamSpace3DVertex, camverts, mstate->numVertices + numClip*9, MEMDUR_FUNCTION);
|
||||||
|
scrverts = rwResizeT(Im2DVertex, scrverts, mstate->numVertices + numClip*9, MEMDUR_FUNCTION);
|
||||||
|
clipindices = rwNewT(uint16, mstate->numPrimitives*3 + numClip*7*3, MEMDUR_FUNCTION);
|
||||||
|
|
||||||
|
clipTriangles(mstate, camverts, scrverts, cullindices, clipindices);
|
||||||
|
|
||||||
|
submitTriangles(scrverts, mstate->numVertices, clipindices, mstate->numPrimitives);
|
||||||
|
|
||||||
|
rwFree(camverts);
|
||||||
|
rwFree(scrverts);
|
||||||
|
rwFree(cullindices);
|
||||||
|
rwFree(clipindices);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
drawAtomic(Atomic *atomic)
|
||||||
|
{
|
||||||
|
MeshState mstate;
|
||||||
|
Matrix lightmat;
|
||||||
|
Geometry *geo;
|
||||||
|
MeshHeader *header;
|
||||||
|
InstanceData *inst;
|
||||||
|
int i;
|
||||||
|
Camera *cam = (Camera*)engine->currentCamera;
|
||||||
|
|
||||||
|
instanceAtomic(atomic);
|
||||||
|
|
||||||
|
mstate.obj2world = *atomic->getFrame()->getLTM();
|
||||||
|
mstate.obj2cam = mstate.obj2world;
|
||||||
|
mstate.obj2cam.transform(&cam->viewMatrix, COMBINEPOSTCONCAT);
|
||||||
|
Matrix::invert(&lightmat, &mstate.obj2world);
|
||||||
|
enumLights(&lightmat);
|
||||||
|
|
||||||
|
geo = atomic->geometry;
|
||||||
|
header = geo->meshHeader;
|
||||||
|
inst = ((InstanceDataHeader*)geo->instData)->inst;
|
||||||
|
for(i = 0; i < header->numMeshes; i++){
|
||||||
|
mstate.flags = geo->flags;
|
||||||
|
mstate.numVertices = inst->numVertices;
|
||||||
|
mstate.numPrimitives = inst->numIndices / 3;
|
||||||
|
mstate.surfProps = inst->material->surfaceProps;
|
||||||
|
mstate.matCol = inst->material->color;
|
||||||
|
drawMesh(&mstate, inst->vertices, inst->indices);
|
||||||
|
inst++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tlTest(Clump *clump)
|
||||||
|
{
|
||||||
|
FORLIST(lnk, clump->atomics){
|
||||||
|
Atomic *a = Atomic::fromClump(lnk);
|
||||||
|
drawAtomic(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static Im2DVertex *clipverts;
|
||||||
|
static int32 numClipverts;
|
||||||
|
|
||||||
|
void
|
||||||
|
genIm3DTransform(void *vertices, int32 numVertices, Matrix *world)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user