add oversampler
This commit is contained in:
762
oversampling/WDL/plush2/pl_cam.cpp
Normal file
762
oversampling/WDL/plush2/pl_cam.cpp
Normal file
@@ -0,0 +1,762 @@
|
||||
/******************************************************************************
|
||||
Plush Version 1.2
|
||||
cam.c
|
||||
Camera and Rendering
|
||||
Copyright (c) 1996-2000, Justin Frankel
|
||||
******************************************************************************/
|
||||
|
||||
#include "plush.h"
|
||||
|
||||
|
||||
#include "../lice/lice_extended.h"
|
||||
|
||||
#include "../mergesort.h"
|
||||
|
||||
#define MACRO_plMatrixApply(m,x,y,z,outx,outy,outz) \
|
||||
( outx ) = ( x )*( m )[0] + ( y )*( m )[1] + ( z )*( m )[2] + ( m )[3];\
|
||||
( outy ) = ( x )*( m )[4] + ( y )*( m )[5] + ( z )*( m )[6] + ( m )[7];\
|
||||
( outz ) = ( x )*( m )[8] + ( y )*( m )[9] + ( z )*( m )[10] + ( m )[11]
|
||||
|
||||
#define MACRO_plDotProduct(x1,y1,z1,x2,y2,z2) \
|
||||
((( x1 )*( x2 ))+(( y1 )*( y2 ))+(( z1 )*( z2 )))
|
||||
|
||||
#define MACRO_plNormalizeVector(x,y,z) { \
|
||||
double length; \
|
||||
length = ( x )*( x )+( y )*( y )+( z )*( z ); \
|
||||
if (length > 0.0000000001) { \
|
||||
double __l = 1.0/sqrt(length); \
|
||||
( x ) *= __l; \
|
||||
( y ) *= __l; \
|
||||
( z ) *= __l; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
static void _FindNormal(double x2, double x3,double y2, double y3,
|
||||
double zv, double *res) {
|
||||
res[0] = zv*(y2-y3);
|
||||
res[1] = zv*(x3-x2);
|
||||
res[2] = x2*y3 - y2*x3;
|
||||
}
|
||||
|
||||
|
||||
void pl_Cam::SetTarget(pl_Float x, pl_Float y, pl_Float z) {
|
||||
double dx, dy, dz;
|
||||
dx = x - X;
|
||||
dy = y - Y;
|
||||
dz = z - Z;
|
||||
Roll = 0;
|
||||
if (dz > 0.0001f) {
|
||||
Pan = (pl_Float) (-atan(dx/dz)*(180.0/PL_PI));
|
||||
dz /= cos(Pan*(PL_PI/180.0));
|
||||
Pitch = (pl_Float) (atan(dy/dz)*(180.0/PL_PI));
|
||||
} else if (dz < -0.0001f) {
|
||||
Pan = (pl_Float) (180.0-atan(dx/dz)*(180.0/PL_PI));
|
||||
dz /= cos((Pan-180.0f)*(PL_PI/180.0));
|
||||
Pitch = (pl_Float) (-atan(dy/dz)*(180.0/PL_PI));
|
||||
} else {
|
||||
Pan = 90.0f;
|
||||
Pitch = (pl_Float) (atan2(dy,-dx) * (180.0 / PL_PI));
|
||||
Roll = -90.0f;
|
||||
}
|
||||
GenMatrix = true;
|
||||
}
|
||||
|
||||
void pl_Cam::RecalcFrustum(int fbw, int fbh)
|
||||
{
|
||||
const int cx = (CenterX*m_lastFBScaling)/256 + fbw/2;
|
||||
const int cy = (CenterY*m_lastFBScaling)/256 + fbh/2;
|
||||
m_lastCX = cx;
|
||||
m_lastCY = cy;
|
||||
|
||||
m_adj_asp = 1.0 / AspectRatio;
|
||||
m_fovfactor = CalcFOVFactor(fbw);
|
||||
memset(m_clipPlanes,0,sizeof(m_clipPlanes));
|
||||
|
||||
/* Back */
|
||||
m_clipPlanes[0][2] = -1.0;
|
||||
m_clipPlanes[0][3] = -ClipBack;
|
||||
|
||||
/* Left */
|
||||
m_clipPlanes[1][3] = 0.00000001;
|
||||
if (cx == 0) m_clipPlanes[1][0] = 1.0;
|
||||
else
|
||||
{
|
||||
_FindNormal(-100,-100,
|
||||
100, -100,
|
||||
m_fovfactor*100.0/cx,
|
||||
m_clipPlanes[1]);
|
||||
if (cx < 0)
|
||||
{
|
||||
m_clipPlanes[1][0] = -m_clipPlanes[1][0];
|
||||
m_clipPlanes[1][1] = -m_clipPlanes[1][1];
|
||||
m_clipPlanes[1][2] = -m_clipPlanes[1][2];
|
||||
}
|
||||
}
|
||||
|
||||
/* Right */
|
||||
m_clipPlanes[2][3] = 0.00000001;
|
||||
if (fbw == cx) m_clipPlanes[2][0] = -1.0;
|
||||
else
|
||||
{
|
||||
_FindNormal(100,100,
|
||||
-100, 100,
|
||||
m_fovfactor*100.0/(fbw-cx),
|
||||
m_clipPlanes[2]);
|
||||
if (cx > fbw)
|
||||
{
|
||||
m_clipPlanes[2][0] = -m_clipPlanes[2][0];
|
||||
m_clipPlanes[2][1] = -m_clipPlanes[2][1];
|
||||
m_clipPlanes[2][2] = -m_clipPlanes[2][2];
|
||||
}
|
||||
}
|
||||
|
||||
/* Top */
|
||||
m_clipPlanes[3][3] = 0.00000001;
|
||||
if (cy == 0) m_clipPlanes[3][1] = 1.0;
|
||||
else
|
||||
{
|
||||
_FindNormal(100, -100,
|
||||
100, 100,
|
||||
m_fovfactor*m_adj_asp*-100.0/(cy),
|
||||
m_clipPlanes[3]);
|
||||
if (cy < 0)
|
||||
{
|
||||
m_clipPlanes[3][0] = -m_clipPlanes[3][0];
|
||||
m_clipPlanes[3][1] = -m_clipPlanes[3][1];
|
||||
m_clipPlanes[3][2] = -m_clipPlanes[3][2];
|
||||
}
|
||||
}
|
||||
|
||||
/* Bottom */
|
||||
m_clipPlanes[4][3] = 0.00000001;
|
||||
if (cy == fbh) m_clipPlanes[4][1] = -1.0;
|
||||
else
|
||||
{
|
||||
_FindNormal(-100, 100,
|
||||
-100, -100,
|
||||
m_fovfactor*m_adj_asp*100.0/(cy-fbh),
|
||||
m_clipPlanes[4]);
|
||||
if (cy > fbh)
|
||||
{
|
||||
m_clipPlanes[4][0] = -m_clipPlanes[4][0];
|
||||
m_clipPlanes[4][1] = -m_clipPlanes[4][1];
|
||||
m_clipPlanes[4][2] = -m_clipPlanes[4][2];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Returns: 0 if nothing gets in, 1 or 2 if pout1 & pout2 get in */
|
||||
pl_uInt pl_Cam::_ClipToPlane(pl_uInt numVerts, pl_Float *plane)
|
||||
{
|
||||
pl_uInt i, nextvert, curin, nextin;
|
||||
double curdot, nextdot, scale;
|
||||
pl_uInt invert, outvert;
|
||||
invert = 0;
|
||||
outvert = 0;
|
||||
curdot = m_cl[0].newVertices[0].xformedx*plane[0] +
|
||||
m_cl[0].newVertices[0].xformedy*plane[1] +
|
||||
m_cl[0].newVertices[0].xformedz*plane[2];
|
||||
curin = (curdot >= plane[3]);
|
||||
|
||||
for (i=0 ; i < numVerts; i++) {
|
||||
nextvert = (i + 1) % numVerts;
|
||||
if (curin) {
|
||||
memcpy(&m_cl[1].ShadeInfos[outvert][0],&m_cl[0].ShadeInfos[invert][0],3*sizeof(pl_Float));
|
||||
int a;
|
||||
for(a=0;a<PLUSH_MAX_MAPCOORDS;a++)
|
||||
{
|
||||
m_cl[1].MappingU[a][outvert] = m_cl[0].MappingU[a][invert];
|
||||
m_cl[1].MappingV[a][outvert] = m_cl[0].MappingV[a][invert];
|
||||
}
|
||||
m_cl[1].newVertices[outvert++] = m_cl[0].newVertices[invert];
|
||||
}
|
||||
nextdot = m_cl[0].newVertices[nextvert].xformedx*plane[0] +
|
||||
m_cl[0].newVertices[nextvert].xformedy*plane[1] +
|
||||
m_cl[0].newVertices[nextvert].xformedz*plane[2];
|
||||
nextin = (nextdot >= plane[3]);
|
||||
if (curin != nextin) {
|
||||
scale = (plane[3] - curdot) / (nextdot - curdot);
|
||||
m_cl[1].newVertices[outvert].xformedx = (pl_Float) (m_cl[0].newVertices[invert].xformedx +
|
||||
(m_cl[0].newVertices[nextvert].xformedx - m_cl[0].newVertices[invert].xformedx)
|
||||
* scale);
|
||||
m_cl[1].newVertices[outvert].xformedy = (pl_Float) (m_cl[0].newVertices[invert].xformedy +
|
||||
(m_cl[0].newVertices[nextvert].xformedy - m_cl[0].newVertices[invert].xformedy)
|
||||
* scale);
|
||||
m_cl[1].newVertices[outvert].xformedz = (pl_Float) (m_cl[0].newVertices[invert].xformedz +
|
||||
(m_cl[0].newVertices[nextvert].xformedz - m_cl[0].newVertices[invert].xformedz)
|
||||
* scale);
|
||||
|
||||
m_cl[1].ShadeInfos[outvert][0] = m_cl[0].ShadeInfos[invert][0] + (m_cl[0].ShadeInfos[nextvert][0] - m_cl[0].ShadeInfos[invert][0]) * scale;
|
||||
m_cl[1].ShadeInfos[outvert][1] = m_cl[0].ShadeInfos[invert][1] + (m_cl[0].ShadeInfos[nextvert][1] - m_cl[0].ShadeInfos[invert][1]) * scale;
|
||||
m_cl[1].ShadeInfos[outvert][2] = m_cl[0].ShadeInfos[invert][2] + (m_cl[0].ShadeInfos[nextvert][2] - m_cl[0].ShadeInfos[invert][2]) * scale;
|
||||
|
||||
int a;
|
||||
for(a=0;a<PLUSH_MAX_MAPCOORDS;a++)
|
||||
{
|
||||
m_cl[1].MappingU[a][outvert] = m_cl[0].MappingU[a][invert] +
|
||||
(m_cl[0].MappingU[a][nextvert] - m_cl[0].MappingU[a][invert]) * scale;
|
||||
m_cl[1].MappingV[a][outvert] = m_cl[0].MappingV[a][invert] +
|
||||
(m_cl[0].MappingV[a][nextvert] - m_cl[0].MappingV[a][invert]) * scale;
|
||||
}
|
||||
outvert++;
|
||||
}
|
||||
curdot = nextdot;
|
||||
curin = nextin;
|
||||
invert++;
|
||||
}
|
||||
return outvert;
|
||||
}
|
||||
|
||||
bool pl_Cam::ProjectCoordinate(pl_Float x, pl_Float y, pl_Float z, pl_Float *screen_x, pl_Float *screen_y, pl_Float *dist)
|
||||
{
|
||||
x -= X;
|
||||
y -= Y;
|
||||
z -= Z;
|
||||
plMatrixApply(CamMatrix,x,y,z,&x,&y,&z);
|
||||
|
||||
if (dist) *dist = sqrt(x*x + y*y + z*z);
|
||||
|
||||
if (!m_lastFBWidth || !m_lastFBHeight || z < 0.0000000001) return false;
|
||||
|
||||
const double iz = 1.0/z;
|
||||
double ytmp = CalcFOVFactor(m_lastFBWidth) * iz;
|
||||
double xtmp = ytmp*x;
|
||||
ytmp *= y*m_adj_asp;
|
||||
|
||||
xtmp += CenterX + m_lastFBWidth/2;
|
||||
ytmp += CenterY + m_lastFBHeight/2;
|
||||
|
||||
if (screen_x) *screen_x = xtmp;
|
||||
if (screen_y) *screen_y = ytmp;
|
||||
|
||||
return xtmp >= 0 && xtmp < m_lastFBWidth && ytmp >= 0 && ytmp < m_lastFBHeight;
|
||||
}
|
||||
|
||||
|
||||
void pl_Cam::ClipRenderFace(pl_Face *face, pl_Obj *obj) {
|
||||
const int cx = m_lastCX, cy = m_lastCY;
|
||||
|
||||
{
|
||||
pl_Vertex *vlist=obj->Vertices.Get();
|
||||
int a;
|
||||
for (a = 0; a < 3; a ++) {
|
||||
m_cl[0].newVertices[a] = vlist[face->VertexIndices[a]];
|
||||
|
||||
memcpy(&m_cl[0].ShadeInfos[a][0],&face->Shades[a][0],3*sizeof(pl_Float));
|
||||
int b;
|
||||
for(b=0;b<PLUSH_MAX_MAPCOORDS;b++)
|
||||
{
|
||||
m_cl[0].MappingU[b][a] = face->MappingU[b][a];
|
||||
m_cl[0].MappingV[b][a] = face->MappingV[b][a];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pl_uInt numVerts = 3;
|
||||
{
|
||||
int a = (m_clipPlanes[0][3] < 0.0 ? 0 : 1);
|
||||
while (a < PL_NUM_CLIP_PLANES && numVerts > 2)
|
||||
{
|
||||
numVerts = _ClipToPlane(numVerts, m_clipPlanes[a]);
|
||||
memcpy(&m_cl[0],&m_cl[1],sizeof(m_cl[0]));
|
||||
a++;
|
||||
}
|
||||
}
|
||||
if (numVerts > 2) {
|
||||
pl_Face newface;
|
||||
memcpy(&newface,face,sizeof(pl_Face));
|
||||
int k;
|
||||
for (k = 2; k < (int)numVerts; k ++) {
|
||||
int a;
|
||||
for (a = 0; a < 3; a ++) {
|
||||
int w;
|
||||
if (a == 0) w = 0;
|
||||
else w = a+(k-2); ;
|
||||
pl_Vertex *thisv=m_cl[0].newVertices+w;
|
||||
newface.Shades[a][0] = m_cl[0].ShadeInfos[w][0];
|
||||
newface.Shades[a][1] = m_cl[0].ShadeInfos[w][1];
|
||||
newface.Shades[a][2] = m_cl[0].ShadeInfos[w][2];
|
||||
int b;
|
||||
for(b=0;b<PLUSH_MAX_MAPCOORDS;b++)
|
||||
{
|
||||
newface.MappingU[b][a] = m_cl[0].MappingU[b][w];
|
||||
newface.MappingV[b][a] = m_cl[0].MappingV[b][w];
|
||||
}
|
||||
newface.Scrz[a] = 1.0f/thisv->xformedz;
|
||||
double ytmp = m_fovfactor * newface.Scrz[a];
|
||||
double xtmp = ytmp*thisv->xformedx;
|
||||
ytmp *= thisv->xformedy*m_adj_asp;
|
||||
newface.Scrx[a] = xtmp+cx;
|
||||
newface.Scry[a] = ytmp+cy;
|
||||
}
|
||||
RenderTrisOut++;
|
||||
|
||||
// quick approx of triangle area
|
||||
RenderPixelsOut += 0.5*fabs(
|
||||
(newface.Scrx[1] - newface.Scrx[0]) *
|
||||
(newface.Scry[2] - newface.Scry[0]) -
|
||||
(newface.Scrx[2] - newface.Scrx[0]) *
|
||||
(newface.Scry[1] - newface.Scry[0]) );
|
||||
|
||||
PutFace(&newface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pl_sInt pl_Cam::ClipNeeded(pl_Face *face, pl_Obj *obj) {
|
||||
const int fbw=m_fBuffer.m_w, fbh=m_fBuffer.m_h;
|
||||
const int cx = m_lastCX, cy = m_lastCY;
|
||||
double dr,dl,db,dt;
|
||||
double f;
|
||||
dr = (fbw-cx);
|
||||
dl = (-cx);
|
||||
db = (fbh-cy);
|
||||
dt = (-cy);
|
||||
f = m_fovfactor*m_adj_asp;
|
||||
pl_Vertex *vlist=obj->Vertices.Get();
|
||||
pl_Vertex *v0=vlist+face->VertexIndices[0];
|
||||
pl_Vertex *v1=vlist+face->VertexIndices[1];
|
||||
pl_Vertex *v2=vlist+face->VertexIndices[2];
|
||||
|
||||
return ((ClipBack <= 0.0 ||
|
||||
v0->xformedz <= ClipBack ||
|
||||
v1->xformedz <= ClipBack ||
|
||||
v2->xformedz <= ClipBack) &&
|
||||
(v0->xformedz >= 0 ||
|
||||
v1->xformedz >= 0 ||
|
||||
v2->xformedz >= 0) &&
|
||||
(v0->xformedx*m_fovfactor<=dr*v0->xformedz ||
|
||||
v1->xformedx*m_fovfactor<=dr*v1->xformedz ||
|
||||
v2->xformedx*m_fovfactor<=dr*v2->xformedz) &&
|
||||
(v0->xformedx*m_fovfactor>=dl*v0->xformedz ||
|
||||
v1->xformedx*m_fovfactor>=dl*v1->xformedz ||
|
||||
v2->xformedx*m_fovfactor>=dl*v2->xformedz) &&
|
||||
(v0->xformedy*f<=db*v0->xformedz ||
|
||||
v1->xformedy*f<=db*v1->xformedz ||
|
||||
v2->xformedy*f<=db*v2->xformedz) &&
|
||||
(v0->xformedy*f>=dt*v0->xformedz ||
|
||||
v1->xformedy*f>=dt*v1->xformedz ||
|
||||
v2->xformedy*f>=dt*v2->xformedz));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void pl_Cam::Begin(LICE_IBitmap *fb, bool want_zbclear, pl_ZBuffer zbclear) {
|
||||
if (WDL_NOT_NORMALLY(m_fBuffer.m_buf) || WDL_NOT_NORMALLY(!fb)) return;
|
||||
|
||||
m_lastFBWidth=fb->getWidth();
|
||||
m_lastFBHeight=fb->getHeight();
|
||||
m_lastFBScaling = (int)fb->Extended(LICE_EXT_GET_SCALING,NULL);
|
||||
if (m_lastFBScaling==0 || WDL_NOT_NORMALLY(m_lastFBScaling > 1024)) m_lastFBScaling=256;
|
||||
|
||||
m_fBuffer.m_buf = fb->getBits();
|
||||
m_fBuffer.m_span = fb->getRowSpan();
|
||||
m_fBuffer.m_w = fb->getWidth() * m_lastFBScaling / 256;
|
||||
m_fBuffer.m_h = fb->getHeight() * m_lastFBScaling / 256;
|
||||
m_fBuffer.m_flipped = fb->isFlipped();
|
||||
|
||||
if (WantZBuffer)
|
||||
{
|
||||
int zbsz=m_fBuffer.m_w*m_fBuffer.m_h;
|
||||
pl_ZBuffer *zb=zBuffer.ResizeOK(zbsz);
|
||||
if (!zb) zBuffer.Resize(0);
|
||||
else if (want_zbclear)
|
||||
{
|
||||
if (!zbclear) memset(zb,0,zbsz*sizeof(pl_ZBuffer));
|
||||
else
|
||||
{
|
||||
int i=zbsz;
|
||||
while(i--) *zb++=zbclear;
|
||||
}
|
||||
}
|
||||
}
|
||||
else zBuffer.Resize(0);
|
||||
pl_Float tempMatrix[16];
|
||||
_numlights = 0;
|
||||
_numfaces = _numfaces_sorted = 0;
|
||||
if (GenMatrix)
|
||||
{
|
||||
plMatrixRotate(CamMatrix,2,-Pan);
|
||||
plMatrixRotate(tempMatrix,1,-Pitch);
|
||||
plMatrixMultiply(CamMatrix,tempMatrix);
|
||||
plMatrixRotate(tempMatrix,3,-Roll);
|
||||
plMatrixMultiply(CamMatrix,tempMatrix);
|
||||
}
|
||||
|
||||
RecalcFrustum(m_fBuffer.m_w, m_fBuffer.m_h);
|
||||
|
||||
RenderTrisIn=RenderTrisCulled=RenderTrisOut=0;
|
||||
RenderPixelsOut=0.0;
|
||||
|
||||
}
|
||||
|
||||
void pl_Cam::RenderLight(pl_Light *light) {
|
||||
if (!light||WDL_NOT_NORMALLY(!m_fBuffer.m_buf)) return;
|
||||
|
||||
pl_Float *pl, xp, yp, zp;
|
||||
if (light->Type == PL_LIGHT_NONE) return;
|
||||
if (_lights.GetSize()<=_numlights) _lights.Resize(_numlights+1);
|
||||
pl = _lights.Get()[_numlights].l;
|
||||
if (light->Type == PL_LIGHT_VECTOR) {
|
||||
xp = light->Xp;
|
||||
yp = light->Yp;
|
||||
zp = light->Zp;
|
||||
MACRO_plMatrixApply(CamMatrix,xp,yp,zp,pl[0],pl[1],pl[2]);
|
||||
} else if (light->Type & PL_LIGHT_POINT) {
|
||||
xp = light->Xp-X;
|
||||
yp = light->Yp-Y;
|
||||
zp = light->Zp-Z;
|
||||
MACRO_plMatrixApply(CamMatrix,xp,yp,zp,pl[0],pl[1],pl[2]);
|
||||
}
|
||||
_lights.Get()[_numlights++].light = light;
|
||||
}
|
||||
|
||||
void pl_Cam::RenderObject(pl_Obj *obj, const pl_Float *bmatrix, const pl_Float *bnmatrix) {
|
||||
if (!obj||WDL_NOT_NORMALLY(!m_fBuffer.m_buf)) return;
|
||||
|
||||
pl_Float oMatrix[16], nMatrix[16], tempMatrix[16];
|
||||
|
||||
if (obj->GenMatrix) {
|
||||
plMatrixRotate(nMatrix,1,obj->Xa);
|
||||
plMatrixRotate(tempMatrix,2,obj->Ya);
|
||||
plMatrixMultiply(nMatrix,tempMatrix);
|
||||
plMatrixRotate(tempMatrix,3,obj->Za);
|
||||
plMatrixMultiply(nMatrix,tempMatrix);
|
||||
memcpy(obj->RotMatrix,nMatrix,sizeof(pl_Float)*16);
|
||||
|
||||
memcpy(oMatrix,nMatrix,sizeof(pl_Float)*16);
|
||||
plMatrixTranslate(tempMatrix, obj->Xp, obj->Yp, obj->Zp);
|
||||
plMatrixMultiply(oMatrix,tempMatrix);
|
||||
memcpy(obj->Matrix,oMatrix,sizeof(pl_Float)*16);
|
||||
} else {
|
||||
memcpy(oMatrix,obj->Matrix,sizeof(pl_Float)*16);
|
||||
memcpy(nMatrix,obj->RotMatrix,sizeof(pl_Float)*16);
|
||||
}
|
||||
|
||||
if (bnmatrix) plMatrixMultiply(nMatrix,bnmatrix);
|
||||
if (bmatrix) plMatrixMultiply(oMatrix,bmatrix);
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < obj->Children.GetSize(); i ++)
|
||||
if (obj->Children.Get(i)) RenderObject(obj->Children.Get(i),oMatrix,nMatrix);
|
||||
}
|
||||
if (!obj->Faces.GetSize() || !obj->Vertices.GetSize()) return;
|
||||
|
||||
plMatrixTranslate(tempMatrix, -X, -Y, -Z);
|
||||
plMatrixMultiply(oMatrix,tempMatrix);
|
||||
plMatrixMultiply(oMatrix,CamMatrix);
|
||||
plMatrixMultiply(nMatrix,CamMatrix);
|
||||
|
||||
{
|
||||
pl_Vertex *vertex = obj->Vertices.Get();
|
||||
int i = obj->Vertices.GetSize();
|
||||
|
||||
while (i--)
|
||||
{
|
||||
MACRO_plMatrixApply(oMatrix,vertex->x,vertex->y,vertex->z,
|
||||
vertex->xformedx, vertex->xformedy, vertex->xformedz);
|
||||
MACRO_plMatrixApply(nMatrix,vertex->nx,vertex->ny,vertex->nz,
|
||||
vertex->xformednx,vertex->xformedny,vertex->xformednz);
|
||||
vertex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_faces.GetSize() < _numfaces + obj->Faces.GetSize()) _faces.Resize(_numfaces + obj->Faces.GetSize());
|
||||
|
||||
|
||||
_faceInfo *facelistout = _faces.Get() + _numfaces;
|
||||
|
||||
pl_Face *face = obj->Faces.Get();
|
||||
int facecnt = obj->Faces.GetSize();
|
||||
|
||||
RenderTrisIn += facecnt;
|
||||
_numfaces += facecnt;
|
||||
pl_Vertex *vlist = obj->Vertices.Get();
|
||||
|
||||
while (facecnt--)
|
||||
{
|
||||
double nx,ny,nz;
|
||||
pl_Mat *mat=face->Material;
|
||||
if (mat->BackfaceCull || (mat->Lightable && !mat->Smoothing))
|
||||
{
|
||||
MACRO_plMatrixApply(nMatrix,face->nx,face->ny,face->nz,nx,ny,nz);
|
||||
}
|
||||
pl_Vertex *v0=vlist+face->VertexIndices[0];
|
||||
pl_Vertex *v1=vlist+face->VertexIndices[1];
|
||||
pl_Vertex *v2=vlist+face->VertexIndices[2];
|
||||
|
||||
if (!mat->BackfaceCull || (MACRO_plDotProduct(nx,ny,nz, v0->xformedx, v0->xformedy, v0->xformedz) < 0.0000001)) {
|
||||
if (ClipNeeded(face,obj)) {
|
||||
if (!mat->Smoothing && (mat->Lightable||mat->FadeDist)) {
|
||||
pl_Float val[3];
|
||||
memcpy(val,face->sLighting,3*sizeof(pl_Float));
|
||||
if (mat->Lightable) {
|
||||
_lightInfo *inf = _lights.Get();
|
||||
int i=_numlights;
|
||||
while (i--)
|
||||
{
|
||||
pl_Light *light = inf->light;
|
||||
double lightsc=0.0;
|
||||
if (light->Type & PL_LIGHT_POINT_ANGLE) {
|
||||
double nx2 = inf->l[0] - v0->xformedx;
|
||||
double ny2 = inf->l[1] - v0->xformedy;
|
||||
double nz2 = inf->l[2] - v0->xformedz;
|
||||
MACRO_plNormalizeVector(nx2,ny2,nz2);
|
||||
lightsc = MACRO_plDotProduct(nx,ny,nz,nx2,ny2,nz2);
|
||||
}
|
||||
if (light->Type & PL_LIGHT_POINT_DISTANCE) {
|
||||
double nx2 = inf->l[0] - v0->xformedx;
|
||||
double ny2 = inf->l[1] - v0->xformedy;
|
||||
double nz2 = inf->l[2] - v0->xformedz;
|
||||
if (light->Type & PL_LIGHT_POINT_ANGLE) {
|
||||
nx2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/
|
||||
light->HalfDistSquared));
|
||||
lightsc *= plMax(0,plMin(1.0,nx2));
|
||||
} else {
|
||||
lightsc = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/
|
||||
light->HalfDistSquared));
|
||||
lightsc = plMax(0,plMin(1.0,lightsc));
|
||||
}
|
||||
}
|
||||
if (light->Type == PL_LIGHT_VECTOR)
|
||||
lightsc = MACRO_plDotProduct(nx,ny,nz,inf->l[0],inf->l[1],inf->l[2]);
|
||||
|
||||
if (lightsc>0.0)
|
||||
{
|
||||
val[0] += light->Intensity[0]*lightsc;
|
||||
val[1] += light->Intensity[1]*lightsc;
|
||||
val[2] += light->Intensity[2]*lightsc;
|
||||
}
|
||||
else if (mat->BackfaceIllumination)
|
||||
{
|
||||
val[0] -= light->Intensity[0]*lightsc*mat->BackfaceIllumination;
|
||||
val[1] -= light->Intensity[1]*lightsc*mat->BackfaceIllumination;
|
||||
val[2] -= light->Intensity[2]*lightsc*mat->BackfaceIllumination;
|
||||
}
|
||||
inf++;
|
||||
} /* End of light loop */
|
||||
} /* End of flat shading if */
|
||||
|
||||
if (mat->FadeDist)
|
||||
{
|
||||
double lightsc = 1.0 - (v0->xformedz+v1->xformedz+v2->xformedz) / (mat->FadeDist*3.0);
|
||||
if (lightsc<0.0) lightsc=0.0;
|
||||
else if (lightsc>1.0)lightsc=1.0;
|
||||
if (mat->Lightable)
|
||||
{
|
||||
val[0] *= lightsc;
|
||||
val[1] *= lightsc;
|
||||
val[2] *= lightsc;
|
||||
}
|
||||
else
|
||||
{
|
||||
val[0]+=lightsc;
|
||||
val[1]+=lightsc;
|
||||
val[2]+=lightsc;
|
||||
}
|
||||
}
|
||||
face->Shades[0][0]=mat->Ambient[0] + mat->Diffuse[0]*val[0];
|
||||
face->Shades[0][1]=mat->Ambient[1] + mat->Diffuse[1]*val[1];
|
||||
face->Shades[0][2]=mat->Ambient[2] + mat->Diffuse[2]*val[2];
|
||||
}
|
||||
else memcpy(face->Shades,mat->Ambient,sizeof(mat->Ambient)); // flat shading
|
||||
|
||||
if ((mat->Texture && mat->TexMapIdx<0)||(mat->Texture2 && mat->Tex2MapIdx<0)) {
|
||||
face->MappingU[PLUSH_MAX_MAPCOORDS-1][0] = 0.5 + (v0->xformednx);
|
||||
face->MappingV[PLUSH_MAX_MAPCOORDS-1][0] = 0.5 - (v0->xformedny);
|
||||
face->MappingU[PLUSH_MAX_MAPCOORDS-1][1] = 0.5 + (v1->xformednx);
|
||||
face->MappingV[PLUSH_MAX_MAPCOORDS-1][1] = 0.5 - (v1->xformedny);
|
||||
face->MappingU[PLUSH_MAX_MAPCOORDS-1][2] = 0.5 + (v2->xformednx);
|
||||
face->MappingV[PLUSH_MAX_MAPCOORDS-1][2] = 0.5 - (v2->xformedny);
|
||||
}
|
||||
|
||||
if (mat->Smoothing && (mat->Lightable || mat->FadeDist))
|
||||
{
|
||||
int a;
|
||||
for (a = 0; a < 3; a ++) {
|
||||
pl_Float val[3];
|
||||
memcpy(val,face->vsLighting[a],sizeof(val));
|
||||
pl_Vertex *thisvert = obj->Vertices.Get()+face->VertexIndices[a];
|
||||
|
||||
if (mat->Lightable)
|
||||
{
|
||||
int i=_numlights;
|
||||
_lightInfo *inf = _lights.Get();
|
||||
while (i--)
|
||||
{
|
||||
double lightsc = 0.0;
|
||||
pl_Light *light = inf->light;
|
||||
if (light->Type & PL_LIGHT_POINT_ANGLE) {
|
||||
double nx2 = inf->l[0] - thisvert->xformedx;
|
||||
double ny2 = inf->l[1] - thisvert->xformedy;
|
||||
double nz2 = inf->l[2] - thisvert->xformedz;
|
||||
MACRO_plNormalizeVector(nx2,ny2,nz2);
|
||||
lightsc = MACRO_plDotProduct(thisvert->xformednx,
|
||||
thisvert->xformedny,
|
||||
thisvert->xformednz,
|
||||
nx2,ny2,nz2);
|
||||
}
|
||||
if (light->Type & PL_LIGHT_POINT_DISTANCE) {
|
||||
double nx2 = inf->l[0] - thisvert->xformedx;
|
||||
double ny2 = inf->l[1] - thisvert->xformedy;
|
||||
double nz2 = inf->l[2] - thisvert->xformedz;
|
||||
if (light->Type & PL_LIGHT_POINT_ANGLE) {
|
||||
double t= (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared));
|
||||
lightsc *= plMax(0,plMin(1.0,t));
|
||||
} else {
|
||||
lightsc = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared));
|
||||
lightsc = plMax(0,plMin(1.0,lightsc));
|
||||
}
|
||||
}
|
||||
|
||||
if (light->Type == PL_LIGHT_VECTOR)
|
||||
lightsc = MACRO_plDotProduct(thisvert->xformednx,
|
||||
thisvert->xformedny,
|
||||
thisvert->xformednz,
|
||||
inf->l[0],inf->l[1],inf->l[2]);
|
||||
if (lightsc > 0.0)
|
||||
{
|
||||
val[0] += lightsc * light->Intensity[0];
|
||||
val[1] += lightsc * light->Intensity[1];
|
||||
val[2] += lightsc * light->Intensity[2];
|
||||
}
|
||||
else if (mat->BackfaceIllumination)
|
||||
{
|
||||
val[0] -= lightsc * light->Intensity[0]*mat->BackfaceIllumination;
|
||||
val[1] -= lightsc * light->Intensity[1]*mat->BackfaceIllumination;
|
||||
val[2] -= lightsc * light->Intensity[2]*mat->BackfaceIllumination;
|
||||
}
|
||||
inf++;
|
||||
} /* End of light loop */
|
||||
} /* End of gouraud shading if */
|
||||
if (mat->FadeDist)
|
||||
{
|
||||
double lightsc = 1.0-thisvert->xformedz/mat->FadeDist;
|
||||
if (lightsc<0.0) lightsc=0.0;
|
||||
else if (lightsc>1.0)lightsc=1.0;
|
||||
if (mat->Lightable)
|
||||
{
|
||||
val[0] *= lightsc;
|
||||
val[1] *= lightsc;
|
||||
val[2] *= lightsc;
|
||||
}
|
||||
else
|
||||
{
|
||||
val[0] += lightsc;
|
||||
val[1] += lightsc;
|
||||
val[2] += lightsc;
|
||||
}
|
||||
}
|
||||
face->Shades[a][0] = mat->Ambient[0] + mat->Diffuse[0]*val[0];
|
||||
face->Shades[a][1] = mat->Ambient[1] + mat->Diffuse[1]*val[1];
|
||||
face->Shades[a][2] = mat->Ambient[2] + mat->Diffuse[2]*val[2];
|
||||
} /* End of vertex loop for */
|
||||
} /* End of gouraud shading mask if */
|
||||
else // flat modes, shade all vertices
|
||||
{
|
||||
memcpy(&face->Shades[1][0],&face->Shades[0][0],sizeof(pl_Float)*3);
|
||||
memcpy(&face->Shades[2][0],&face->Shades[0][0],sizeof(pl_Float)*3);
|
||||
}
|
||||
|
||||
facelistout->zd = v0->xformedz+v1->xformedz+v2->xformedz;
|
||||
facelistout->obj=obj;
|
||||
facelistout->face = face;
|
||||
facelistout++;
|
||||
|
||||
|
||||
RenderTrisCulled++;
|
||||
|
||||
} /* Is it in our area Check */
|
||||
} /* Backface Check */
|
||||
face++;
|
||||
}
|
||||
_numfaces = facelistout-_faces.Get();
|
||||
}
|
||||
void pl_Cam::SortToCurrent()
|
||||
{
|
||||
if (Sort && _numfaces > _numfaces_sorted+1)
|
||||
{
|
||||
WDL_mergesort(_faces.Get()+_numfaces_sorted,
|
||||
_numfaces-_numfaces_sorted,sizeof(_faceInfo),
|
||||
Sort > 0 ? sortFwdFunc : sortRevFunc,
|
||||
(char*)_sort_tmpspace.Resize((_numfaces-_numfaces_sorted)*sizeof(_faceInfo),false));
|
||||
}
|
||||
_numfaces_sorted=_numfaces;
|
||||
}
|
||||
|
||||
int pl_Cam::sortRevFunc(const void *a, const void *b)
|
||||
{
|
||||
_faceInfo *aa = (_faceInfo*)a;
|
||||
_faceInfo *bb = (_faceInfo*)b;
|
||||
|
||||
if (aa->zd < bb->zd) return -1;
|
||||
if (aa->zd > bb->zd) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pl_Cam::sortFwdFunc(const void *a, const void *b)
|
||||
{
|
||||
_faceInfo *aa = (_faceInfo*)a;
|
||||
_faceInfo *bb = (_faceInfo*)b;
|
||||
|
||||
if (aa->zd < bb->zd) return 1;
|
||||
if (aa->zd > bb->zd) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pl_Cam::End() {
|
||||
if (WDL_NOT_NORMALLY(!m_fBuffer.m_buf)) return;
|
||||
|
||||
SortToCurrent();
|
||||
|
||||
_faceInfo *f = _faces.Get();
|
||||
int n=_numfaces;
|
||||
while (n-->0)
|
||||
{
|
||||
if (f->face->Material)
|
||||
{
|
||||
ClipRenderFace(f->face,f->obj);
|
||||
}
|
||||
f++;
|
||||
}
|
||||
|
||||
m_fBuffer.m_buf = NULL;
|
||||
_numfaces=0;
|
||||
_numlights = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pl_Light::Set(pl_uChar mode, pl_Float x, pl_Float y, pl_Float z, pl_Float intensity_r, pl_Float intensity_g, pl_Float intensity_b, pl_Float halfDist) {
|
||||
pl_Float m[16], m2[16];
|
||||
Type = mode;
|
||||
Intensity[0] = intensity_r;
|
||||
Intensity[1] = intensity_g;
|
||||
Intensity[2] = intensity_b;
|
||||
HalfDistSquared = halfDist*halfDist;
|
||||
switch (mode) {
|
||||
case PL_LIGHT_VECTOR:
|
||||
plMatrixRotate(m,1,x);
|
||||
plMatrixRotate(m2,2,y);
|
||||
plMatrixMultiply(m,m2);
|
||||
plMatrixRotate(m2,3,z);
|
||||
plMatrixMultiply(m,m2);
|
||||
plMatrixApply(m,0.0,0.0,-1.0,&Xp, &Yp, &Zp);
|
||||
break;
|
||||
case PL_LIGHT_POINT_ANGLE:
|
||||
case PL_LIGHT_POINT_DISTANCE:
|
||||
case PL_LIGHT_POINT:
|
||||
Xp = x;
|
||||
Yp = y;
|
||||
Zp = z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user