add oversampler

This commit is contained in:
2024-05-24 13:28:31 +02:00
parent e4a4a661a0
commit 989dba5a6b
484 changed files with 313937 additions and 0 deletions

View 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;
}
}

View File

@@ -0,0 +1,537 @@
/******************************************************************************
Plush Version 1.2
make.c
Object Primitives
Copyright (c) 1996-2000, Justin Frankel
*******************************************************************************
Notes:
Most of these routines are highly unoptimized.
They could all use some work, such as more capable divisions (Box is
most notable), etc... The mapping coordinates are all set up nicely,
though.
******************************************************************************/
#include "plush.h"
pl_Obj *plMakeTorus(pl_Float r1, pl_Float r2, pl_uInt divrot, pl_uInt divrad,
pl_Mat *m) {
pl_Obj *o;
pl_Vertex *v;
pl_Face *f;
pl_uInt x, y;
double ravg, rt, a, da, al, dal;
pl_Float U,V,dU,dV;
if (divrot < 3) divrot = 3;
if (divrad < 3) divrad = 3;
ravg = (r1+r2)*0.5;
rt = (r2-r1)*0.5;
o = new pl_Obj(divrad*divrot,divrad*divrot*2);
if (!o) return 0;
v = o->Vertices.Get();
a = 0.0;
da = 2*PL_PI/divrot;
for (y = 0; y < divrot; y ++) {
al = 0.0;
dal = 2*PL_PI/divrad;
for (x = 0; x < divrad; x ++) {
v->x = (pl_Float) (cos((double) a)*(ravg + cos((double) al)*rt));
v->z = (pl_Float) (sin((double) a)*(ravg + cos((double) al)*rt));
v->y = (pl_Float) (sin((double) al)*rt);
v++;
al += dal;
}
a += da;
}
v = o->Vertices.Get();
f = o->Faces.Get();
dV = 1.0/divrad;
dU = 1.0/divrot;
U = 0;
for (y = 0; y < divrot; y ++) {
V = -0.5;
for (x = 0; x < divrad; x ++) {
f->VertexIndices[0] = v+x+y*divrad - o->Vertices.Get();
f->MappingU[0][0] = U;
f->MappingV[0][0] = V;
f->VertexIndices[1] = v+(x+1==divrad?0:x+1)+y*divrad - o->Vertices.Get();
f->MappingU[0][1] = U;
f->MappingV[0][1] = V+dV;
f->VertexIndices[2] = v+x+(y+1==divrot?0:(y+1)*divrad) - o->Vertices.Get();
f->MappingU[0][2] = U+dU;
f->MappingV[0][2] = V;
f->Material = m;
f++;
f->VertexIndices[0] = v+x+(y+1==divrot?0:(y+1)*divrad) - o->Vertices.Get();
f->MappingU[0][0] = U+dU;
f->MappingV[0][0] = V;
f->VertexIndices[1] = v+(x+1==divrad?0:x+1)+y*divrad - o->Vertices.Get();
f->MappingU[0][1] = U;
f->MappingV[0][1] = V+dV;
f->VertexIndices[2] = v+(x+1==divrad?0:x+1)+(y+1==divrot?0:(y+1)*divrad) - o->Vertices.Get();
f->MappingU[0][2] = U+dU;
f->MappingV[0][2] = V+dV;
f->Material = m;
f++;
V += dV;
}
U += dU;
}
o->CalculateNormals();
return (o);
}
pl_Obj *plMakeSphere(pl_Float r, pl_uInt divr, pl_uInt divh, pl_Mat *m) {
pl_Obj *o;
pl_Vertex *v;
pl_Face *f;
pl_uInt x, y;
double a, da, yp, ya, yda, yf;
pl_Float U,V,dU,dV;
if (divh < 3) divh = 3;
if (divr < 3) divr = 3;
o = new pl_Obj(2+(divh-2)*(divr),2*divr+(divh-3)*divr*2);
if (!o) return 0;
v = o->Vertices.Get();
v->x = v->z = 0.0; v->y = r; v++;
v->x = v->z = 0.0; v->y = -r; v++;
ya = 0.0;
yda = PL_PI/(divh-1);
da = (PL_PI*2.0)/divr;
for (y = 0; y < divh - 2; y ++) {
ya += yda;
yp = cos((double) ya)*r;
yf = sin((double) ya)*r;
a = 0.0;
for (x = 0; x < divr; x ++) {
v->y = (pl_Float) yp;
v->x = (pl_Float) (cos((double) a)*yf);
v->z = (pl_Float) (sin((double) a)*yf);
v++;
a += da;
}
}
f = o->Faces.Get();
v = o->Vertices.Get() + 2;
a = 0.0;
U = 0;
dU = 1.0/divr;
dV = V = 1.0/divh;
for (x = 0; x < divr; x ++) {
f->VertexIndices[0] = 0;
f->VertexIndices[1] = v + (x+1==divr ? 0 : x+1) - o->Vertices.Get();
f->VertexIndices[2] = v + x - o->Vertices.Get();
f->MappingU[0][0] = U;
f->MappingV[0][0] = 0;
f->MappingU[0][1] = U+dU;
f->MappingV[0][1] = V;
f->MappingU[0][2] = U;
f->MappingV[0][2] = V;
f->Material = m;
f++;
U += dU;
}
da = 1.0/(divr+1);
v = o->Vertices.Get() + 2;
for (x = 0; x < (divh-3); x ++) {
U = 0;
for (y = 0; y < divr; y ++) {
f->VertexIndices[0] = v+y - o->Vertices.Get();
f->VertexIndices[1] = v+divr+(y+1==divr?0:y+1) - o->Vertices.Get();
f->VertexIndices[2] = v+y+divr - o->Vertices.Get();
f->MappingU[0][0] = U;
f->MappingV[0][0] = V;
f->MappingU[0][1] = U+dU;
f->MappingV[0][1] = V+dV;
f->MappingU[0][2] = U;
f->MappingV[0][2] = V+dV;
f->Material = m; f++;
f->VertexIndices[0] = v+y - o->Vertices.Get();
f->VertexIndices[1] = v+(y+1==divr?0:y+1) - o->Vertices.Get();
f->VertexIndices[2] = v+(y+1==divr?0:y+1)+divr - o->Vertices.Get();
f->MappingU[0][0] = U;
f->MappingV[0][0] = V;
f->MappingU[0][1] = U+dU;
f->MappingV[0][1] = V;
f->MappingU[0][2] = U+dU;
f->MappingV[0][2] = V+dV;
f->Material = m; f++;
U += dU;
}
V += dV;
v += divr;
}
v = o->Vertices.Get() + o->Vertices.GetSize() - divr;
U = 0;
for (x = 0; x < divr; x ++) {
f->VertexIndices[0] = 1;
f->VertexIndices[1] = v + x - o->Vertices.Get();
f->VertexIndices[2] = v + (x+1==divr ? 0 : x+1) - o->Vertices.Get();
f->MappingU[0][0] = U;
f->MappingV[0][0] = 1.0;
f->MappingU[0][1] = U;
f->MappingV[0][1] = V;
f->MappingU[0][2] = U+dU;
f->MappingV[0][2] = V;
f->Material = m;
f++;
U += dU;
}
o->CalculateNormals();
return (o);
}
pl_Obj *plMakeDisc(pl_Float r, pl_uInt divr, pl_Mat *m)
{
pl_Obj *o;
pl_Vertex *v;
pl_Face *f;
pl_uInt32 i;
double a, da;
o=new pl_Obj(divr, divr);
if (!o) return NULL;
a = 0.0;
da = (2.0*PL_PI)/divr;
v = o->Vertices.Get();
for (i = 0; i < divr; i ++)
{
v->y = 0.0;
v->x = (pl_Float) (r*cos((double) a));
v->z = (pl_Float)(r*sin(a));
v->xformedx = (0.5 + (0.5*cos((double) a))); // temp
v->xformedy = (0.5 + (0.5*sin((double) a))); // use xf
v++;
a += da;
}
v = o->Vertices.Get();
f = o->Faces.Get();
for (i = 0; i < divr; i ++)
{
f->VertexIndices[0] = i == divr-1 ? 0 : i + 1;
f->VertexIndices[1] = i;
f->VertexIndices[2] = 0;
f->MappingU[0][0] = v[(i==divr-1?0:i+1)].xformedx;
f->MappingV[0][0] = v[(i==divr-1?0:i+1)].xformedy;
f->MappingU[0][1] = v[i].xformedx;
f->MappingV[0][1] = v[i].xformedy;
f->MappingU[0][2] = f->MappingV[0][2] = 0.5;
f->Material = m;
f++;
}
f->VertexIndices[0] = 0;
f->VertexIndices[1] = 2;
f->VertexIndices[2] = 1;
f->MappingU[0][0] = v[0].xformedx;
f->MappingV[0][0] = v[0].xformedy;
f->MappingU[0][1] = v[1].xformedx;
f->MappingV[0][1] = v[1].xformedy;
f->MappingU[0][2] = v[2].xformedx;
f->MappingV[0][2] = v[2].xformedy;
f->Material = m;
o->CalculateNormals();
return o;
}
pl_Obj *plMakeCylinder(pl_Float r, pl_Float h, pl_uInt divr, pl_Bool captop,
pl_Bool capbottom, pl_Mat *m) {
pl_Obj *o;
pl_Vertex *v, *topverts, *bottomverts, *topcapvert=0, *bottomcapvert=0;
pl_Face *f;
pl_uInt32 i;
double a, da;
if (divr < 3) divr = 3;
o = new pl_Obj(divr*2+((divr==3)?0:(captop?1:0)+(capbottom?1:0)),
divr*2+(divr==3 ? (captop ? 1 : 0) + (capbottom ? 1 : 0) :
(captop ? divr : 0) + (capbottom ? divr : 0)));
if (!o) return 0;
a = 0.0;
da = (2.0*PL_PI)/divr;
v = o->Vertices.Get();
topverts = v;
for (i = 0; i < divr; i ++) {
v->y = h/2.0f;
v->x = (pl_Float) (r*cos((double) a));
v->z = (pl_Float)(r*sin(a));
v->xformedx = (0.5 + (0.5*cos((double) a))); // temp
v->xformedy = (0.5 + (0.5*sin((double) a))); // use xf
v++;
a += da;
}
bottomverts = v;
a = 0.0;
for (i = 0; i < divr; i ++) {
v->y = -h/2.0f;
v->x = (pl_Float) (r*cos((double) a));
v->z = (pl_Float) (r*sin(a));
v->xformedx = (0.5 + (0.5*cos((double) a)));
v->xformedy = (0.5 + (0.5*sin((double) a)));
v++; a += da;
}
if (captop && divr != 3) {
topcapvert = v;
v->y = h / 2.0f;
v->x = v->z = 0.0f;
v++;
}
if (capbottom && divr != 3) {
bottomcapvert = v;
v->y = -h / 2.0f;
v->x = v->z = 0.0f;
v++;
}
f = o->Faces.Get();
for (i = 0; i < divr; i ++) {
f->VertexIndices[0] = bottomverts + i - o->Vertices.Get();
f->VertexIndices[1] = topverts + i - o->Vertices.Get();
f->VertexIndices[2] = bottomverts + (i == divr-1 ? 0 : i+1) - o->Vertices.Get();
f->MappingV[0][0] = f->MappingV[0][2] = 1.0; f->MappingV[0][1] = 0;
f->MappingU[0][0] = f->MappingU[0][1] = i/(double)divr;
f->MappingU[0][2] = ((i+1))/(double)divr;
f->Material = m; f++;
f->VertexIndices[0] = bottomverts + (i == divr-1 ? 0 : i+1) - o->Vertices.Get();
f->VertexIndices[1] = topverts + i - o->Vertices.Get();
f->VertexIndices[2] = topverts + (i == divr-1 ? 0 : i+1) - o->Vertices.Get();
f->MappingV[0][1] = f->MappingV[0][2] = 0; f->MappingV[0][0] = 1.0;
f->MappingU[0][0] = f->MappingU[0][2] = ((i+1))/(double)divr;
f->MappingU[0][1] = (i)/(double)divr;
f->Material = m; f++;
}
if (captop) {
if (divr == 3) {
f->VertexIndices[0] = topverts + 0 - o->Vertices.Get();
f->VertexIndices[1] = topverts + 2 - o->Vertices.Get();
f->VertexIndices[2] = topverts + 1 - o->Vertices.Get();
f->MappingU[0][0] = topverts[0].xformedx;
f->MappingV[0][0] = topverts[0].xformedy;
f->MappingU[0][1] = topverts[1].xformedx;
f->MappingV[0][1] = topverts[1].xformedy;
f->MappingU[0][2] = topverts[2].xformedx;
f->MappingV[0][2] = topverts[2].xformedy;
f->Material = m; f++;
} else {
for (i = 0; i < divr; i ++) {
f->VertexIndices[0] = topverts + (i == divr-1 ? 0 : i + 1) - o->Vertices.Get();
f->VertexIndices[1] = topverts + i - o->Vertices.Get();
f->VertexIndices[2] = topcapvert - o->Vertices.Get();
f->MappingU[0][0] = topverts[(i==divr-1?0:i+1)].xformedx;
f->MappingV[0][0] = topverts[(i==divr-1?0:i+1)].xformedy;
f->MappingU[0][1] = topverts[i].xformedx;
f->MappingV[0][1] = topverts[i].xformedy;
f->MappingU[0][2] = f->MappingV[0][2] = 0.5;
f->Material = m; f++;
}
}
}
if (capbottom) {
if (divr == 3) {
f->VertexIndices[0] = bottomverts + 0 - o->Vertices.Get();
f->VertexIndices[1] = bottomverts + 1 - o->Vertices.Get();
f->VertexIndices[2] = bottomverts + 2 - o->Vertices.Get();
f->MappingU[0][0] = bottomverts[0].xformedx;
f->MappingV[0][0] = bottomverts[0].xformedy;
f->MappingU[0][1] = bottomverts[1].xformedx;
f->MappingV[0][1] = bottomverts[1].xformedy;
f->MappingU[0][2] = bottomverts[2].xformedx;
f->MappingV[0][2] = bottomverts[2].xformedy;
f->Material = m; f++;
} else {
for (i = 0; i < divr; i ++) {
f->VertexIndices[0] = bottomverts + i - o->Vertices.Get();
f->VertexIndices[1] = bottomverts + (i == divr-1 ? 0 : i + 1) - o->Vertices.Get();
f->VertexIndices[2] = bottomcapvert - o->Vertices.Get();
f->MappingU[0][0] = bottomverts[i].xformedx;
f->MappingV[0][0] = bottomverts[i].xformedy;
f->MappingU[0][1] = bottomverts[(i==divr-1?0:i+1)].xformedx;
f->MappingV[0][1] = bottomverts[(i==divr-1?0:i+1)].xformedy;
f->MappingU[0][2] = f->MappingV[0][2] = 0.5;
f->Material = m; f++;
}
}
}
o->CalculateNormals();
return (o);
}
pl_Obj *plMakeCone(pl_Float r, pl_Float h, pl_uInt div,
pl_Bool cap, pl_Mat *m) {
pl_Obj *o;
pl_Vertex *v;
pl_Face *f;
pl_uInt32 i;
double a, da;
if (div < 3) div = 3;
o = new pl_Obj(div + (div == 3 ? 1 : (cap ? 2 : 1)),
div + (div == 3 ? 1 : (cap ? div : 0)));
if (!o) return 0;
v = o->Vertices.Get();
v->x = v->z = 0; v->y = h/2;
v->xformedx = 0.5;
v->xformedy = 0.5;
v++;
a = 0.0;
da = (2.0*PL_PI)/div;
for (i = 1; i <= div; i ++) {
v->y = h/-2.0f;
v->x = (pl_Float) (r*cos((double) a));
v->z = (pl_Float) (r*sin((double) a));
v->xformedx = (0.5 + (cos((double) a)*0.5));
v->xformedy = (0.5 + (sin((double) a)*0.5));
a += da;
v++;
}
if (cap && div != 3) {
v->y = h / -2.0f;
v->x = v->z = 0.0f;
v->xformedx = 0.5;
v->xformedy = 0.5;
v++;
}
f = o->Faces.Get();
for (i = 1; i <= div; i ++) {
f->VertexIndices[0] = 0;
f->VertexIndices[1] = o->Vertices.Get() + (i == div ? 1 : i + 1) - o->Vertices.Get();
f->VertexIndices[2] = o->Vertices.Get() + i - o->Vertices.Get();
f->MappingU[0][0] = o->Vertices.Get()[0].xformedx;
f->MappingV[0][0] = o->Vertices.Get()[0].xformedy;
f->MappingU[0][1] = o->Vertices.Get()[(i==div?1:i+1)].xformedx;
f->MappingV[0][1] = o->Vertices.Get()[(i==div?1:i+1)].xformedy;
f->MappingU[0][2] = o->Vertices.Get()[i].xformedx;
f->MappingV[0][2] = o->Vertices.Get()[i].xformedy;
f->Material = m;
f++;
}
if (cap) {
if (div == 3) {
f->VertexIndices[0] = 1;
f->VertexIndices[1] = 2;
f->VertexIndices[2] = 3;
f->MappingU[0][0] = o->Vertices.Get()[1].xformedx;
f->MappingV[0][0] = o->Vertices.Get()[1].xformedy;
f->MappingU[0][1] = o->Vertices.Get()[2].xformedx;
f->MappingV[0][1] = o->Vertices.Get()[2].xformedy;
f->MappingU[0][2] = o->Vertices.Get()[3].xformedx;
f->MappingV[0][2] = o->Vertices.Get()[3].xformedy;
f->Material = m;
f++;
} else {
for (i = 1; i <= div; i ++) {
f->VertexIndices[0] = div + 1;
f->VertexIndices[1] = i;
f->VertexIndices[2] = (i==div ? 1 : i+1);
f->MappingU[0][0] = o->Vertices.Get()[div+1].xformedx;
f->MappingV[0][0] = o->Vertices.Get()[div+1].xformedy;
f->MappingU[0][1] = o->Vertices.Get()[i].xformedx;
f->MappingV[0][1] = o->Vertices.Get()[i].xformedy;
f->MappingU[0][2] = o->Vertices.Get()[i==div?1:i+1].xformedx;
f->MappingV[0][2] = o->Vertices.Get()[i==div?1:i+1].xformedy;
f->Material = m;
f++;
}
}
}
o->CalculateNormals();
return (o);
}
static pl_uChar verts[6*6] = {
0,4,1, 1,4,5, 0,1,2, 3,2,1, 2,3,6, 3,7,6,
6,7,4, 4,7,5, 1,7,3, 7,1,5, 2,6,0, 4,0,6
};
static pl_uChar map[24*2*3] = {
1,0, 1,1, 0,0, 0,0, 1,1, 0,1,
0,0, 1,0, 0,1, 1,1, 0,1, 1,0,
0,0, 1,0, 0,1, 1,0, 1,1, 0,1,
0,0, 1,0, 0,1, 0,1, 1,0, 1,1,
1,0, 0,1, 0,0, 0,1, 1,0, 1,1,
1,0, 1,1, 0,0, 0,1, 0,0, 1,1
};
pl_Obj *plMakeBox(pl_Float w, pl_Float d, pl_Float h, pl_Mat *m) {
pl_uChar *mm = map;
pl_uChar *vv = verts;
pl_Obj *o;
pl_Vertex *v;
pl_Face *f;
pl_uInt x;
o = new pl_Obj(8,12);
if (!o) return 0;
v = o->Vertices.Get();
v->x = -w/2; v->y = h/2; v->z = d/2; v++;
v->x = w/2; v->y = h/2; v->z = d/2; v++;
v->x = -w/2; v->y = h/2; v->z = -d/2; v++;
v->x = w/2; v->y = h/2; v->z = -d/2; v++;
v->x = -w/2; v->y = -h/2; v->z = d/2; v++;
v->x = w/2; v->y = -h/2; v->z = d/2; v++;
v->x = -w/2; v->y = -h/2; v->z = -d/2; v++;
v->x = w/2; v->y = -h/2; v->z = -d/2; v++;
f = o->Faces.Get();
for (x = 0; x < 12; x ++) {
f->VertexIndices[0] = *vv++;
f->VertexIndices[1] = *vv++;
f->VertexIndices[2] = *vv++;
f->MappingU[0][0] = (pl_Float) *mm++;
f->MappingV[0][0] = (pl_Float) *mm++;
f->MappingU[0][1] = (pl_Float) *mm++;
f->MappingV[0][1] = (pl_Float) *mm++;
f->MappingU[0][2] = (pl_Float) *mm++;
f->MappingV[0][2] = (pl_Float) *mm++;
f->Material = m;
f++;
}
o->CalculateNormals();
return (o);
}
pl_Obj *plMakePlane(pl_Float w, pl_Float d, pl_uInt res, pl_Mat *m) {
pl_Obj *o;
pl_Vertex *v;
pl_Face *f;
pl_uInt x, y;
o = new pl_Obj((res+1)*(res+1),res*res*2);
if (!o) return 0;
v = o->Vertices.Get();
for (y = 0; y <= res; y ++) {
for (x = 0; x <= res; x ++) {
v->y = 0;
v->x = ((x*w)/res) - w/2;
v->z = ((y*d)/res) - d/2;
v++;
}
}
f = o->Faces.Get();
for (y = 0; y < res; y ++) {
for (x = 0; x < res; x ++) {
f->VertexIndices[0] = x+(y*(res+1));
f->MappingU[0][0] = (x)/(double)res;
f->MappingV[0][0] = (y)/(double)res;
f->VertexIndices[2] = x+1+(y*(res+1));
f->MappingU[0][2] = ((x+1))/(double)res;
f->MappingV[0][2] = (y)/(double)res;
f->VertexIndices[1] = x+((y+1)*(res+1));
f->MappingU[0][1] = (x)/(double)res;
f->MappingV[0][1] = ((y+1))/(double)res;
f->Material = m;
f++;
f->VertexIndices[0] = x+((y+1)*(res+1));
f->MappingU[0][0] = (x)/(double)res;
f->MappingV[0][0] = ((y+1))/(double)res;
f->VertexIndices[2] = x+1+(y*(res+1));
f->MappingU[0][2] = ((x+1))/(double)res;
f->MappingV[0][2] = (y)/(double)res;
f->VertexIndices[1] = x+1+((y+1)*(res+1));
f->MappingU[0][1] = ((x+1))/(double)res;
f->MappingV[0][1] = ((y+1))/(double)res;
f->Material = m;
f++;
}
}
o->CalculateNormals();
return (o);
}

View File

@@ -0,0 +1,67 @@
/******************************************************************************
Plush Version 1.2
math.c
Math and Matrix Control
Copyright (c) 1996-2000, Justin Frankel
******************************************************************************/
#include "plush.h"
void plMatrixRotate(pl_Float matrix[], pl_uChar m, pl_Float Deg) {
pl_uChar m1, m2;
double c,s;
double d= Deg * PL_PI / 180.0;
memset(matrix,0,sizeof(pl_Float)*16);
matrix[((m-1)<<2)+m-1] = matrix[15] = 1.0;
m1 = (m % 3);
m2 = ((m1+1) % 3);
c = cos(d); s = sin(d);
matrix[(m1<<2)+m1]=(pl_Float)c; matrix[(m1<<2)+m2]=(pl_Float)s;
matrix[(m2<<2)+m2]=(pl_Float)c; matrix[(m2<<2)+m1]=(pl_Float)-s;
}
void plMatrixTranslate(pl_Float m[], pl_Float x, pl_Float y, pl_Float z) {
memset(m,0,sizeof(pl_Float)*16);
m[0] = m[4+1] = m[8+2] = m[12+3] = 1.0;
m[0+3] = x; m[4+3] = y; m[8+3] = z;
}
void plMatrixMultiply(pl_Float *dest, const pl_Float src[]) {
pl_Float temp[16];
pl_uInt i;
memcpy(temp,dest,sizeof(pl_Float)*16);
for (i = 0; i < 16; i += 4) {
*dest++ = src[i+0]*temp[(0<<2)+0]+src[i+1]*temp[(1<<2)+0]+
src[i+2]*temp[(2<<2)+0]+src[i+3]*temp[(3<<2)+0];
*dest++ = src[i+0]*temp[(0<<2)+1]+src[i+1]*temp[(1<<2)+1]+
src[i+2]*temp[(2<<2)+1]+src[i+3]*temp[(3<<2)+1];
*dest++ = src[i+0]*temp[(0<<2)+2]+src[i+1]*temp[(1<<2)+2]+
src[i+2]*temp[(2<<2)+2]+src[i+3]*temp[(3<<2)+2];
*dest++ = src[i+0]*temp[(0<<2)+3]+src[i+1]*temp[(1<<2)+3]+
src[i+2]*temp[(2<<2)+3]+src[i+3]*temp[(3<<2)+3];
}
}
void plMatrixApply(pl_Float *m, pl_Float x, pl_Float y, pl_Float z,
pl_Float *outx, pl_Float *outy, pl_Float *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];
}
pl_Float plDotProduct(pl_Float x1, pl_Float y1, pl_Float z1,
pl_Float x2, pl_Float y2, pl_Float z2) {
return ((x1*x2)+(y1*y2)+(z1*z2));
}
void plNormalizeVector(pl_Float *x, pl_Float *y, pl_Float *z) {
double length;
length = (*x)*(*x)+(*y)*(*y)+(*z)*(*z);
if (length > 0.0000000001) {
pl_Float t = (pl_Float)sqrt(length);
*x /= t;
*y /= t;
*z /= t;
} else *x = *y = *z = 0.0;
}

View File

@@ -0,0 +1,129 @@
/******************************************************************************
Plush Version 1.2
obj.c
Object control
Copyright (c) 1996-2000, Justin Frankel
******************************************************************************/
#include "plush.h"
void pl_Obj::Scale(pl_Float s) {
int i = Vertices.GetSize();
pl_Vertex *v = Vertices.Get();
while (i--) {
v->x *= s; v->y *= s; v->z *= s; v++;
}
for (i = 0; i < Children.GetSize(); i ++)
if (Children.Get(i)) Children.Get(i)->Scale(s);
}
void pl_Obj::Stretch(pl_Float x, pl_Float y, pl_Float z) {
int i = Vertices.GetSize();
pl_Vertex *v = Vertices.Get();
while (i--) {
v->x *= x; v->y *= y; v->z *= z; v++;
}
for (i = 0; i < Children.GetSize(); i ++)
if (Children.Get(i)) Children.Get(i)->Stretch(x,y,z);
}
void pl_Obj::Translate(pl_Float x, pl_Float y, pl_Float z) {
int i = Vertices.GetSize();
pl_Vertex *v = Vertices.Get();
while (i--) {
v->x += x; v->y += y; v->z += z; v++;
}
for (i = 0; i < Children.GetSize(); i ++)
if (Children.Get(i)) Children.Get(i)->Translate(x,y,z);
}
void pl_Obj::FlipNormals() {
int i = Vertices.GetSize();
pl_Vertex *v = Vertices.Get();
pl_Face *f = Faces.Get();
while (i--) {
v->nx = - v->nx; v->ny = - v->ny; v->nz = - v->nz; v++;
}
i = Faces.GetSize();
while (i--) {
f->nx = - f->nx; f->ny = - f->ny; f->nz = - f->nz;
f++;
}
for (i = 0; i < Children.GetSize(); i ++)
if (Children.Get(i)) Children.Get(i)->FlipNormals();
}
pl_Obj *pl_Obj::Clone() {
int i;
pl_Obj *out;
if (!(out = new pl_Obj(Vertices.GetSize(),Faces.GetSize()))) return 0;
for (i = 0; i < Children.GetSize(); i ++)
out->Children.Add(Children.Get(i) ? Children.Get(i)->Clone() : NULL);
out->Xa = Xa; out->Ya = Ya; out->Za = Za;
out->Xp = Xp; out->Yp = Yp; out->Zp = Zp;
out->GenMatrix = GenMatrix;
memcpy(out->Matrix,Matrix,sizeof(Matrix));
memcpy(out->Vertices.Get(), Vertices.Get(), sizeof(pl_Vertex) * Vertices.GetSize());
memcpy(out->Faces.Get(),Faces.Get(),sizeof(pl_Face) * Faces.GetSize());
return out;
}
void pl_Obj::SetMaterial(pl_Mat *m, pl_Bool th) {
pl_sInt32 i = Faces.GetSize();
pl_Face *f = Faces.Get();
while (i--) (f++)->Material = m;
if (th) for (i = 0; i < Children.GetSize(); i++)
if (Children.Get(i)) Children.Get(i)->SetMaterial(m,true);
}
void pl_Obj::CalculateNormals() {
int i;
pl_Vertex *v = Vertices.Get();
pl_Face *f = Faces.Get();
double x1, x2, y1, y2, z1, z2;
i = Vertices.GetSize();
while (i--) {
v->nx = 0.0; v->ny = 0.0; v->nz = 0.0;
v++;
}
i = Faces.GetSize();
while (i--) {
pl_Vertex *vp=Vertices.Get();
pl_Vertex *fVertices[3] = {
vp+f->VertexIndices[0],
vp+f->VertexIndices[1],
vp+f->VertexIndices[2],
};
x1 = fVertices[0]->x-fVertices[1]->x;
x2 = fVertices[0]->x-fVertices[2]->x;
y1 = fVertices[0]->y-fVertices[1]->y;
y2 = fVertices[0]->y-fVertices[2]->y;
z1 = fVertices[0]->z-fVertices[1]->z;
z2 = fVertices[0]->z-fVertices[2]->z;
f->nx = (pl_Float) (y1*z2 - z1*y2);
f->ny = (pl_Float) (z1*x2 - x1*z2);
f->nz = (pl_Float) (x1*y2 - y1*x2);
plNormalizeVector(&f->nx, &f->ny, &f->nz);
fVertices[0]->nx += f->nx;
fVertices[0]->ny += f->ny;
fVertices[0]->nz += f->nz;
fVertices[1]->nx += f->nx;
fVertices[1]->ny += f->ny;
fVertices[1]->nz += f->nz;
fVertices[2]->nx += f->nx;
fVertices[2]->ny += f->ny;
fVertices[2]->nz += f->nz;
f++;
}
v = Vertices.Get();
i = Vertices.GetSize();
do {
plNormalizeVector(&v->nx, &v->ny, &v->nz);
v++;
} while (--i);
for (i = 0; i < Children.GetSize(); i ++)
if (Children.Get(i)) Children.Get(i)->CalculateNormals();
}

View File

@@ -0,0 +1,446 @@
static void
#ifdef PL_PF_MULTITEX
PLMTexTri
#else
PLTexTri
#endif
(LICE_pixel *gmem, int swidth, pl_Face *TriFace, pl_ZBuffer *zbuf, int zfb_width, bool zb_update,
int solidalpha, int solidcomb, LICE_IBitmap *tex, pl_Float *texscales, int texalpha, int texcomb, int texmap
#ifdef PL_PF_MULTITEX
, LICE_IBitmap *tex2, int tex2alpha, int tex2comb, int texmap2
#endif
)
{
pl_sInt32 C1[3], C3[3], C2[3], dC2[3]={0}, dCL[3]={0},dC1[3]={0}, dX2=0, dX1=0;
pl_Float dZ2=0, dZL=0,dZ1=0;
PUTFACE_SORT();
solidcomb&=LICE_BLIT_MODE_MASK;
if (solidcomb == 0 && solidalpha == 256) solidcomb=-1;
else if (solidalpha==0) solidcomb=-2; // ignore
int solidalpha2=(256-solidalpha)*256;
pl_Float dU2=0,dV2=0,dUL=0,dVL=0;
pl_Float dU1=0, dV1=0;
bool bilinear = (texcomb&LICE_BLIT_FILTER_MASK)==LICE_BLIT_FILTER_BILINEAR;
texcomb&=LICE_BLIT_MODE_MASK|LICE_BLIT_USE_ALPHA;
if (texcomb==LICE_BLIT_MODE_COPY && texalpha==256) texcomb=-1;
else if (texalpha==0) texcomb=-2;
int texalpha2=(256-texalpha);
int tex_rowspan=0;
LICE_pixel *texture=NULL;
int tex_w=16,tex_h=16;
#if defined(PLUSH_NO_SOLIDGOURAUD) || defined(PLUSH_NO_TEXTURE)
if (tex)
#endif
{
texture=tex->getBits();
tex_rowspan = tex->getRowSpan();
if (tex->isFlipped())
{
texture += tex_rowspan*(tex->getHeight()-1);
tex_rowspan=-tex_rowspan;
}
tex_w=tex->getWidth();
tex_h=tex->getHeight();
tex_rowspan *= 4;
}
pl_sInt32 MappingU_Max=tex_w<<16, MappingV_Max=tex_h<<16;
texscales[0]*=MappingU_Max;
texscales[1]*=MappingV_Max;
tex_w *= 4;
#ifdef PL_PF_MULTITEX
pl_Float dU2_2=0,dV2_2=0,dUL_2=0,dVL_2=0;
pl_Float dU1_2=0, dV1_2=0;
int tex_w_2=16,tex_h_2=16;
bool bilinear2 = (tex2comb&LICE_BLIT_FILTER_MASK)==LICE_BLIT_FILTER_BILINEAR;
tex2comb&=LICE_BLIT_MODE_MASK|LICE_BLIT_USE_ALPHA;
if (tex2comb==LICE_BLIT_MODE_COPY && tex2alpha==256) tex2comb=-1;
else if (tex2alpha==0) tex2comb=-2;
int tex2alpha2=(256-tex2alpha);
LICE_pixel *texture_2=NULL;
int tex_rowspan_2 = 0;
pl_sInt32 MappingU_Max_2, MappingV_Max_2;
#ifdef PLUSH_NO_TEXTURE
if (tex2)
#endif
{
tex_w_2=tex2->getWidth();
tex_h_2=tex2->getHeight();
texture_2=tex2->getBits();
tex_rowspan_2 = tex2->getRowSpan();
if (tex2->isFlipped())
{
texture_2 += tex_rowspan_2*(tex2->getHeight()-1);
tex_rowspan_2=-tex_rowspan_2;
}
tex_rowspan_2 *= 4;
}
MappingU_Max_2=tex_w_2<<16;
MappingV_Max_2=tex_h_2<<16;
texscales[2]*=MappingU_Max_2;
texscales[3]*=MappingV_Max_2;
tex_w_2 *= 4;
#endif
pl_uChar nm = TriFace->Material->PerspectiveCorrect;
pl_uChar nmb = 0; while (nm) { nmb++; nm >>= 1; }
nmb = plMin(6,nmb);
nm = 1<<nmb;
pl_Float Z1 = TriFace->Scrz[i0];
pl_Float Z2 = TriFace->Scrz[i1];
pl_Float Z3 = TriFace->Scrz[i2];
pl_Float MappingU1=TriFace->MappingU[texmap][i0]*texscales[0]*Z1;
pl_Float MappingV1=TriFace->MappingV[texmap][i0]*texscales[1]*Z1;
pl_Float MappingU2=TriFace->MappingU[texmap][i1]*texscales[0]*Z2;
pl_Float MappingV2=TriFace->MappingV[texmap][i1]*texscales[1]*Z2;
pl_Float MappingU3=TriFace->MappingU[texmap][i2]*texscales[0]*Z3;
pl_Float MappingV3=TriFace->MappingV[texmap][i2]*texscales[1]*Z3;
#ifdef PL_PF_MULTITEX
pl_Float MappingU1_2=TriFace->MappingU[texmap2][i0]*texscales[2]*Z1;
pl_Float MappingV1_2=TriFace->MappingV[texmap2][i0]*texscales[3]*Z1;
pl_Float MappingU2_2=TriFace->MappingU[texmap2][i1]*texscales[2]*Z2;
pl_Float MappingV2_2=TriFace->MappingV[texmap2][i1]*texscales[3]*Z2;
pl_Float MappingU3_2=TriFace->MappingU[texmap2][i2]*texscales[2]*Z3;
pl_Float MappingV3_2=TriFace->MappingV[texmap2][i2]*texscales[3]*Z3;
#endif
int a;
for(a=0;a<3;a++)
{
C1[a] = (pl_sInt32) (TriFace->Shades[i0][a]*(1<<24));
C2[a] = (pl_sInt32) (TriFace->Shades[i1][a]*(1<<24));
C3[a] = (pl_sInt32) (TriFace->Shades[i2][a]*(1<<24));
}
pl_Float U1, U2;
U1 = U2 = MappingU1;
pl_Float V1,V2;
V1 = V2 = MappingV1;
#ifdef PL_PF_MULTITEX
pl_Float U1_2, U2_2;
U1_2 = U2_2 = MappingU1_2;
pl_Float V1_2, V2_2;
V1_2 = V2_2 = MappingV1_2;
#endif
pl_sInt32 X2,X1;
X2 = X1 = Scrx[i0];
pl_sInt32 Y0 = Scry[i0];
pl_sInt32 Y1 = Scry[i1];
pl_sInt32 Y2 = Scry[i2];
{
pl_sInt32 dY = Y2-Y0;
if (dY) {
dX2 = (Scrx[i2] - X1) / dY;
pl_Float v = 1.0/dY;
for(a=0;a<3;a++) dC2[a] = (pl_sInt32) ((C3[a] - C1[a]) * v);
dZ2 = (Z3 - Z1) * v;
dU2 = (MappingU3 - U1) * v;
dV2 = (MappingV3 - V1) * v;
#ifdef PL_PF_MULTITEX
dU2_2 = (MappingU3_2 - U1_2) * v;
dV2_2 = (MappingV3_2 - V1_2) * v;
#endif
}
dY = Y1-Y0;
if (dY) {
dX1 = (Scrx[i1] - X1) / dY;
pl_Float v=1.0/dY;
dZ1 = (Z2 - Z1) * v;
for(a=0;a<3;a++) dC1[a] = (pl_sInt32) ((C2[a] - C1[a]) * v);
dU1 = (MappingU2 - U1) * v;
dV1 = (MappingV2 - V1) * v;
#ifdef PL_PF_MULTITEX
dU1_2 = (MappingU2_2 - U1_2) * v;
dV1_2 = (MappingV2_2 - V1_2) * v;
#endif
if (dX2 < dX1) {
SWAP(dX1,dX2,pl_sInt32);
SWAP(dU1,dU2,pl_Float);
SWAP(dV1,dV2,pl_Float);
#ifdef PL_PF_MULTITEX
SWAP(dU1_2,dU2_2,pl_Float);
SWAP(dV1_2,dV2_2,pl_Float);
#endif
SWAP(dZ1,dZ2,pl_Float);
for(a=0;a<3;a++)
SWAP(dC1[a],dC2[a],pl_sInt32);
stat = 2;
} else stat = 1;
Z2 = Z1;
C2[0] = C1[0];
C2[1] = C1[1];
C2[2] = C1[2];
} else {
if (Scrx[i1] > X1) {
X2 = Scrx[i1];
U2 = MappingU2;
V2 = MappingV2;
#ifdef PL_PF_MULTITEX
U2_2 = MappingU2_2;
V2_2 = MappingV2_2;
#endif
stat = 2|4;
} else {
X1 = Scrx[i1];
SWAP(Z1,Z2,pl_Float)
for(a=0;a<3;a++) SWAP(C1[a],C2[a],pl_sInt32);
U1 = MappingU2;
V1 = MappingV2;
#ifdef PL_PF_MULTITEX
U1_2 = MappingU2_2;
V1_2 = MappingV2_2;
#endif
stat = 1|8;
}
}
pl_sInt32 tmp = (dX1-dX2)*dY;
if (tmp) {
pl_Float v=(1<<XPOS_BITS)/(double)tmp;
dUL = ((dU1-dU2)*dY)*v;
dVL = ((dV1-dV2)*dY)*v;
#ifdef PL_PF_MULTITEX
dUL_2 = ((dU1_2-dU2_2)*dY)*v;
dVL_2 = ((dV1_2-dV2_2)*dY)*v;
#endif
dZL = ((dZ1-dZ2)*dY)*v;
for(a=0;a<3;a++) dCL[a] = (pl_sInt32) ( ((dC1[a]-dC2[a])*dY)*v);
} else {
tmp = X2-X1;
if (tmp) {
pl_Float v=(1<<XPOS_BITS)/(double)tmp;
dUL = (U2-U1)*v;
dVL = (V2-V1)*v;
#ifdef PL_PF_MULTITEX
dUL_2 = (U2_2-U1_2)*v;
dVL_2 = (V2_2-V1_2)*v;
#endif
dZL = (Z2-Z1)*v;
for(a=0;a<3;a++) dCL[a] = (pl_sInt32) ((C2[a]-C1[a])*v);
}
}
}
gmem += (Y0 * swidth);
zbuf += (Y0 * zfb_width);
pl_Float pdZL = dZL * nm;
dUL *= nm;
dVL *= nm;
#ifdef PL_PF_MULTITEX
dUL_2 *= nm;
dVL_2 *= nm;
#endif
Y1 -= Y0;
Y0 = Y2-Y0;
while (Y0--) {
if (!Y1--) {
pl_sInt32 dY = Y2-Scry[i1];
if (dY) {
DO_STAT_XDELTAS
pl_Float tmp=1.0/dY;
dZ1 = (Z3-Z1)*tmp;
for(a=0;a<3;a++) dC1[a] = (pl_sInt32)((C3[a]-C1[a])*tmp);
dV1 = (MappingV3 - V1)*tmp;
dU1 = (MappingU3 - U1)*tmp;
#ifdef PL_PF_MULTITEX
dV1_2 = (MappingV3_2 - V1_2)*tmp;
dU1_2 = (MappingU3_2 - U1_2)*tmp;
#endif
}
}
pl_sInt32 XL1 = (X1+(1<<(XPOS_BITS-1)))>>XPOS_BITS;
pl_sInt32 Xlen = ((X2+(1<<(XPOS_BITS-1)))>>XPOS_BITS) - XL1;
if (Xlen > 0) {
pl_sInt32 iUL, iVL, idUL, idVL, iULnext, iVLnext;
pl_Float UL = U1;
pl_Float VL = V1;
#ifdef PL_PF_MULTITEX
pl_sInt32 iUL_2, iVL_2, idUL_2, idVL_2, iULnext_2, iVLnext_2;
pl_Float UL_2 = U1_2;
pl_Float VL_2 = V1_2;
#endif
pl_sInt32 CL[3] = {C1[0],C1[1], C1[2]};
pl_Float pZL,ZL;
pl_Float t = 1.0f / (pZL = ZL = Z1);
gmem += XL1;
zbuf += XL1;
XL1 += Xlen; // update to new line end pos so we can adjust gmem/zbuf later
iULnext = ((pl_sInt32) (UL*t));
iVLnext = ((pl_sInt32) (VL*t));
#ifdef PL_PF_MULTITEX
iULnext_2 = ((pl_sInt32) (UL_2*t));
iVLnext_2 = ((pl_sInt32) (VL_2*t));
#endif
do {
UL += dUL;
VL += dVL;
iUL = iULnext;
iVL = iVLnext;
pZL += pdZL;
t = 1.0f/pZL;
iULnext = ((pl_sInt32) (UL*t));
iVLnext = ((pl_sInt32) (VL*t));
idUL = (iULnext - iUL)>>nmb;
idVL = (iVLnext - iVL)>>nmb;
if (idUL>MappingU_Max) idUL=MappingU_Max;
else if (idUL<-MappingU_Max) idUL=-MappingU_Max;
if (idVL>MappingV_Max) idVL=MappingV_Max;
else if (idVL<-MappingV_Max) idVL=-MappingV_Max;
// todo: this is slow as shit, should we force textures to be powers of two? hehe
if (iUL<0) do iUL+=MappingU_Max; while (iUL<0);
else while (iUL >= MappingU_Max) iUL-=MappingU_Max;
if (iVL<0) do iVL+=MappingV_Max; while (iVL<0);
else while (iVL >= MappingV_Max) iVL-=MappingV_Max;
#ifdef PL_PF_MULTITEX
UL_2 += dUL_2;
VL_2 += dVL_2;
iUL_2 = iULnext_2;
iVL_2 = iVLnext_2;
iULnext_2 = ((pl_sInt32) (UL_2*t));
iVLnext_2 = ((pl_sInt32) (VL_2*t));
idUL_2 = (iULnext_2 - iUL_2)>>nmb;
idVL_2 = (iVLnext_2 - iVL_2)>>nmb;
if (idUL_2>MappingU_Max_2) idUL_2=MappingU_Max_2;
else if (idUL_2<-MappingU_Max_2) idUL_2=-MappingU_Max_2;
if (idVL_2>MappingV_Max_2) idVL_2=MappingV_Max_2;
else if (idVL_2<-MappingV_Max_2) idVL_2=-MappingV_Max_2;
// todo: this is slow as shit, should we force textures to be powers of two? hehe
if (iUL_2<0) do iUL_2+=MappingU_Max_2; while (iUL_2<0);
else while (iUL_2 >= MappingU_Max_2) iUL_2-=MappingU_Max_2;
if (iVL_2<0) do iVL_2+=MappingV_Max_2; while (iVL_2<0);
else while (iVL_2 >= MappingV_Max_2) iVL_2-=MappingV_Max_2;
#endif
pl_uInt n = nm;
Xlen -= n;
if (Xlen < 0) n += Xlen;
if (zfb_width) do {
if (*zbuf < ZL) {
if (zb_update) *zbuf = (pl_ZBuffer) ZL;
#ifdef PL_PF_MULTITEX
TextureMakePixel2((LICE_pixel_chan *)gmem,solidcomb,solidalpha,solidalpha2,CL, bilinear,
iUL,iVL,tex_w,tex_h,texture,tex_rowspan,texcomb,texalpha,texalpha2,
bilinear2, iUL_2,iVL_2,
tex_w_2,tex_h_2,
texture_2,tex_rowspan_2,tex2comb,tex2alpha,tex2alpha2);
#else
TextureMakePixel((LICE_pixel_chan *)gmem,solidcomb,solidalpha,solidalpha2,CL, bilinear, iUL,iVL,
tex_w,tex_h,
texture,tex_rowspan,texcomb,texalpha,texalpha2);
#endif
}
zbuf++;
gmem++;
ZL += dZL;
CL[0] += dCL[0];
CL[1] += dCL[1];
CL[2] += dCL[2];
iUL += idUL;
iVL += idVL;
if (iUL<0) iUL+=MappingU_Max;
else if (iUL >= MappingU_Max) iUL -= MappingU_Max;
if (iVL<0) iVL+=MappingV_Max;
else if (iVL >= MappingV_Max) iVL -= MappingV_Max;
#ifdef PL_PF_MULTITEX
iUL_2 += idUL_2;
iVL_2 += idVL_2;
if (iUL_2<0) iUL_2+=MappingU_Max_2;
else if (iUL_2 >= MappingU_Max_2) iUL_2 -= MappingU_Max_2;
if (iVL_2<0) iVL_2+=MappingV_Max_2;
else if (iVL_2 >= MappingV_Max_2) iVL_2 -= MappingV_Max_2;
#endif
} while (--n);
else do {
#ifdef PL_PF_MULTITEX
TextureMakePixel2((LICE_pixel_chan *)gmem,solidcomb,solidalpha,solidalpha2,CL, bilinear,
iUL,iVL,tex_w,tex_h,texture,tex_rowspan,texcomb,texalpha,texalpha2,
bilinear2, iUL_2,iVL_2,
tex_w_2,tex_h_2,
texture_2,tex_rowspan_2,tex2comb,tex2alpha,tex2alpha2);
#else
TextureMakePixel((LICE_pixel_chan *)gmem,solidcomb,solidalpha,solidalpha2,CL, bilinear, iUL,iVL,
tex_w,tex_h,
texture,tex_rowspan,texcomb,texalpha,texalpha2);
#endif
gmem++;
CL[0] += dCL[0];
CL[1] += dCL[1];
CL[2] += dCL[2];
iUL += idUL;
iVL += idVL;
if (iUL<0) iUL+=MappingU_Max;
else if (iUL >= MappingU_Max) iUL -= MappingU_Max;
if (iVL<0) iVL+=MappingV_Max;
else if (iVL >= MappingV_Max) iVL -= MappingV_Max;
#ifdef PL_PF_MULTITEX
iUL_2 += idUL_2;
iVL_2 += idVL_2;
if (iUL_2<0) iUL_2+=MappingU_Max_2;
else if (iUL_2 >= MappingU_Max_2) iUL_2 -= MappingU_Max_2;
if (iVL_2<0) iVL_2+=MappingV_Max_2;
else if (iVL_2 >= MappingV_Max_2) iVL_2 -= MappingV_Max_2;
#endif
} while (--n);
} while (Xlen > 0);
gmem += swidth-XL1;
zbuf += zfb_width-XL1;
} else { // xlen <=0 ,no drawing
gmem += swidth;
zbuf += zfb_width;
}
Z1 += dZ1;
U1 += dU1;
V1 += dV1;
#ifdef PL_PF_MULTITEX
U1_2 += dU1_2;
V1_2 += dV1_2;
#endif
X1 += dX1;
X2 += dX2;
C1[0] += dC1[0];
C1[1] += dC1[1];
C1[2] += dC1[2];
}
}

View File

@@ -0,0 +1,713 @@
#include "plush.h"
#include "../lice/lice_combine.h"
//#define PLUSH_NO_SOLIDFLAT // make non-texturemapped flat shading optimized engine
//#define PLUSH_NO_SOLIDGOURAUD // disable non-texturemapped gouraud optimized engine
//#define PLUSH_NO_TEXTURE // disable single-texture optimized engine
//#define PLUSH_NO_MULTITEXTURE // disable multitexture (this can do any of em)
#define XPOS_BITS 19 // allows 2^13 max screen width, or 8192px
#define SWAP(a,b,t) { t ____tmp=(a); (a)=(b); (b)=____tmp; }
#define PUTFACE_SORT() \
int i0 = 0; int i1 = 1; int i2 = 2; int stat; \
if (TriFace->Scry[0] > TriFace->Scry[1]) { i0 = 1; i1 = 0; } \
if (TriFace->Scry[i0] > TriFace->Scry[2]) { SWAP(i0,i2,int); } \
if (TriFace->Scry[i1] > TriFace->Scry[i2]) { SWAP(i1,i2,int); } \
int Scrx[3] = {(int)(TriFace->Scrx[0]*(1<<XPOS_BITS)), (int)(TriFace->Scrx[1]*(1<<XPOS_BITS)),(int)(TriFace->Scrx[2]*(1<<XPOS_BITS))}; \
int Scry[3] = {(int) (TriFace->Scry[0]+0.5), (int) (TriFace->Scry[1]+0.5), (int) (TriFace->Scry[2]+0.5)}; \
#define DO_STAT_XDELTAS \
if (stat & 1) { \
dX1 = (Scrx[i2]-(X1 = Scrx[i1]))/dY; \
if (stat & 8) dX2 = (Scrx[i2]-(X2 = Scrx[i0]))/dY; \
} \
else if (stat & 2) { \
dX2 = (Scrx[i2]-(X2 = Scrx[i1]))/dY; \
if (stat & 4) dX1 = (Scrx[i2]-(X1 = Scrx[i0]))/dY; \
}
static inline void OverlayBlend(int &red, int &green, int &blue, int &alpha, int r, int g, int b, int a, int usea)
{
int da=(256-usea)*128;
int srcr = r*usea+da, srcg = g*usea+da, srcb = b*usea+da, srca = usea*a + da;
red = ( red*( (red*(32768-srcr))/256 + srcr ) )/32768;
green = ( green*( (green*(32768-srcg))/256 + srcg ) )/32768;
blue = ( blue*( (blue*(32768-srcb))/256 + srcb ) )/32768;
alpha = ( alpha*( (alpha*(32768-srca))/256 + srca ) )/32768;
}
static inline void MulBlend(int &red, int &green, int &blue, int &alpha, int r, int g, int b, int a, int ta)
{
int ta2=(256-ta)*256;
red = (r*ta*red + red*ta2)/65536;
green = (g*ta*green + green*ta2)/65536;
blue = (b*ta*blue + blue*ta2)/65536;
alpha = (a*ta*alpha + alpha*ta2)/65536;
}
static inline void AdjustHSV(int &red, int &green, int &blue, int r, int g, int b, int texalpha)
{
int h,s,v;
__LICE_RGB2HSV(red,green,blue,&h,&s,&v);
h+=(((r+r/2) - 192) * texalpha)/256;
if (h<0)h+=384;
else if (h>=384) h-=384;
s+=((g-128)*texalpha)/256;
if (s&~0xff)
{
if (s<0)s=0;
else s=255;
}
v+=((b-128)*texalpha)/256;
if (v&~0xff)
{
if (v<0)v=0;
else v=255;
}
__LICE_HSV2RGB(h,s,v,&red,&green,&blue);
}
static inline void DodgeBlend(int &red, int &green, int &blue, int &alpha, int r, int g, int b, int a, int ta)
{
int src_r = 256-r*ta/256;
int src_g = 256-g*ta/256;
int src_b = 256-b*ta/256;
int src_a = 256-(a*ta)/256;
red = src_r > 1 ? 256*red / src_r : 256*red;
green = src_g > 1 ? 256*green / src_g : 256*green;
blue = src_b > 1 ? 256*blue / src_b : 256*blue;
alpha = src_a > 1 ? 256*alpha / src_a : 256*alpha;
}
static void inline DoTextureCombine(int texcomb, int r, int g, int b, int a, int &red, int &green, int &blue, int &alpha, int texalpha, int texalpha2)
{
switch (texcomb)
{
case LICE_BLIT_MODE_COPY:
red = (r*texalpha + red*texalpha2) >> 8;
green = (g*texalpha + green*texalpha2) >> 8;
blue = (b*texalpha + blue*texalpha2) >> 8;
alpha = (a*texalpha + alpha*texalpha2) >> 8;
break;
case LICE_BLIT_MODE_ADD:
red += (r*texalpha) >> 8;
green += (g*texalpha) >> 8;
blue += (b*texalpha) >> 8;
alpha += (a*texalpha) >> 8;
break;
case LICE_BLIT_MODE_MUL:
MulBlend(red,green,blue,alpha,r,g,b,a,texalpha);
break;
case LICE_BLIT_MODE_DODGE:
DodgeBlend(red,green,blue,alpha,r,g,b,a,texalpha);
break;
case LICE_BLIT_MODE_OVERLAY:
OverlayBlend(red,green,blue,alpha,r,g,b,a, texalpha);
break;
case LICE_BLIT_MODE_HSVADJ:
AdjustHSV(red,green,blue,r,g,b,texalpha);
break;
case LICE_BLIT_MODE_COPY|LICE_BLIT_USE_ALPHA:
{
int ta=(texalpha*(a+1));
int ta2=(65536-ta);
red = (r*ta + red*ta2) >> 16;
green = (g*ta + green*ta2) >> 16;
blue = (b*ta + blue*ta2) >> 16;
alpha = (a*ta + alpha*ta2) >> 16;
}
break;
case LICE_BLIT_MODE_ADD|LICE_BLIT_USE_ALPHA:
{
int ta=(texalpha*(a+1));
red += (r*ta) >> 16;
green += (g*ta) >> 16;
blue += (b*ta) >> 16;
alpha += (a*ta) >> 16;
}
break;
case LICE_BLIT_MODE_DODGE|LICE_BLIT_USE_ALPHA:
{
int ta=(texalpha*(a+1))/256;
DodgeBlend(red,green,blue,alpha,r,g,b,a,ta);
}
break;
case LICE_BLIT_MODE_MUL|LICE_BLIT_USE_ALPHA:
MulBlend(red,green,blue,alpha,r,g,b,a,(texalpha*(a+1))/256);
break;
case LICE_BLIT_MODE_OVERLAY|LICE_BLIT_USE_ALPHA:
OverlayBlend(red,green,blue,alpha,r,g,b,a, (texalpha*(a+1))/256);
break;
case LICE_BLIT_MODE_HSVADJ|LICE_BLIT_USE_ALPHA:
AdjustHSV(red,green,blue,r,g,b,(texalpha*(a+1))/256);
break;
case -2:
break;
default:
red=r; green=g; blue=b; alpha=a;
break;
}
}
static void inline TextureMakePixelSolidCombine(int &red, int &green, int &blue, int &alpha,
pl_sInt32 *CL, int solidcomb, int solidalpha,
int solidalpha2,
LICE_pixel_chan *gmemptr)
{
switch (solidcomb)
{
case LICE_BLIT_MODE_COPY:
red = ((CL[0]>>8)*solidalpha + gmemptr[LICE_PIXEL_R]*solidalpha2)>>16;
green = ((CL[1]>>8)*solidalpha + gmemptr[LICE_PIXEL_G]*solidalpha2)>>16;
blue = ((CL[2]>>8)*solidalpha + gmemptr[LICE_PIXEL_B]*solidalpha2)>>16;
alpha = solidalpha;
break;
case LICE_BLIT_MODE_ADD:
red = gmemptr[LICE_PIXEL_R] + (((CL[0]>>8)*solidalpha)>>16);
green = gmemptr[LICE_PIXEL_G] + (((CL[1]>>8)*solidalpha)>>16);
blue = gmemptr[LICE_PIXEL_B] + (((CL[2]>>8)*solidalpha)>>16);
alpha = gmemptr[LICE_PIXEL_A] + solidalpha;
break;
case LICE_BLIT_MODE_DODGE:
red=gmemptr[LICE_PIXEL_R];
green=gmemptr[LICE_PIXEL_G];
blue=gmemptr[LICE_PIXEL_B];
alpha=gmemptr[LICE_PIXEL_A];
DodgeBlend(red,green,blue,alpha,CL[0]>>16,CL[1]>>16,CL[2]>>16,solidalpha,solidalpha);
break;
case LICE_BLIT_MODE_MUL:
red=gmemptr[LICE_PIXEL_R];
green=gmemptr[LICE_PIXEL_G];
blue=gmemptr[LICE_PIXEL_B];
alpha=gmemptr[LICE_PIXEL_A];
MulBlend(red,green,blue,alpha,CL[0]>>16,CL[1]>>16,CL[2]>>16,solidalpha,solidalpha);
break;
case LICE_BLIT_MODE_OVERLAY:
red=gmemptr[LICE_PIXEL_R];
green=gmemptr[LICE_PIXEL_G];
blue=gmemptr[LICE_PIXEL_B];
alpha=gmemptr[LICE_PIXEL_A];
OverlayBlend(red,green,blue,alpha,CL[0]>>16,CL[1]>>16,CL[2]>>16,solidalpha, solidalpha);
break;
case LICE_BLIT_MODE_HSVADJ:
red=gmemptr[LICE_PIXEL_R];
green=gmemptr[LICE_PIXEL_G];
blue=gmemptr[LICE_PIXEL_B];
alpha=gmemptr[LICE_PIXEL_A];
AdjustHSV(red,green,blue,CL[0]>>16,CL[1]>>16,CL[2]>>16,solidalpha);
break;
case -2:
red=gmemptr[LICE_PIXEL_R];
green=gmemptr[LICE_PIXEL_G];
blue=gmemptr[LICE_PIXEL_B];
alpha=gmemptr[LICE_PIXEL_A];
break;
default:
red=CL[0]>>16;
green=CL[1]>>16;
blue=CL[2]>>16;
alpha=solidalpha;
break;
}
}
static void inline TextureMakePixel2(LICE_pixel_chan *gmemptr,
int solidcomb, int solidalpha, int solidalpha2,
pl_sInt32 *CL,
bool bilinear,
pl_sInt32 iUL, pl_sInt32 iVL,
pl_sInt32 texwidth, pl_sInt32 texheight,
LICE_pixel *texture, int tex_rowspan,
int texcomb,
int texalpha,
int texalpha2,
bool bilinear2,
pl_sInt32 iUL_2, pl_sInt32 iVL_2,
pl_sInt32 texwidth_2, pl_sInt32 texheight_2,
LICE_pixel *texture2, int tex_rowspan_2,
int tex2comb,
int tex2alpha,
int tex2alpha2)
{
int red,green,blue,alpha;
TextureMakePixelSolidCombine(red,green,blue,alpha,CL,solidcomb,solidalpha,solidalpha2,gmemptr);
int r,g,b,a;
#if defined(PLUSH_NO_TEXTURE)
if (texture)
#endif
{
const int xpos=(iUL>>14)&~3;
const int ypos=iVL>>16;
const LICE_pixel_chan *rd = ((LICE_pixel_chan*)texture) + xpos+ypos*tex_rowspan;
if (bilinear)
{
__LICE_BilinearFilterI_2(&r,&g,&b,&a,rd,
ypos < texheight - 1 ? rd+tex_rowspan : ((LICE_pixel_chan *)texture)+xpos,
xpos < texwidth - 4 ? 4 : 4-texwidth,
iUL&65535,iVL&65535);
}
else
{
r=rd[LICE_PIXEL_R]; g=rd[LICE_PIXEL_G]; b=rd[LICE_PIXEL_B]; a=rd[LICE_PIXEL_A];
}
DoTextureCombine(texcomb, r,g,b,a, red,green,blue,alpha,texalpha,texalpha2);
}
#ifdef PLUSH_NO_TEXTURE
if (texture2)
#endif
{
const int xpos=(iUL_2>>14)&~3;
const int ypos=iVL_2>>16;
const LICE_pixel_chan *rd = ((LICE_pixel_chan*)texture2) + xpos+ypos*tex_rowspan_2;
if (bilinear2)
{
__LICE_BilinearFilterI_2(&r,&g,&b,&a,rd,
ypos < texheight_2 - 1 ? rd+tex_rowspan_2 : ((LICE_pixel_chan *)texture2)+xpos,
xpos < texwidth_2 - 4 ? 4 : 4-texwidth_2,
iUL_2&65535,iVL_2&65535);
}
else
{
r=rd[LICE_PIXEL_R]; g=rd[LICE_PIXEL_G]; b=rd[LICE_PIXEL_B]; a=rd[LICE_PIXEL_A];
}
DoTextureCombine(tex2comb, r,g,b,a, red,green,blue,alpha,tex2alpha,tex2alpha2);
}
_LICE_MakePixelClamp(gmemptr, red,green,blue,alpha);
}
static void inline TextureMakePixel(LICE_pixel_chan *gmemptr,
int solidcomb, int solidalpha, int solidalpha2,
pl_sInt32 *CL,
bool bilinear,
pl_sInt32 iUL, pl_sInt32 iVL,
pl_sInt32 texwidth, pl_sInt32 texheight,
LICE_pixel *texture, int tex_rowspan,
int texcomb,
int texalpha,
int texalpha2)
{
int red,green,blue,alpha;
if (
#ifdef PLUSH_NO_SOLIDGOURAUD
!texture||
#endif
texcomb!=-1)
TextureMakePixelSolidCombine(red,green,blue,alpha,CL,solidcomb,solidalpha,solidalpha2,gmemptr);
#ifdef PLUSH_NO_SOLIDGOURAUD
if (texture)
#endif
{
int r,g,b,a;
const int xpos=(iUL>>14)&~3;
const int ypos=iVL>>16;
const LICE_pixel_chan *rd = ((LICE_pixel_chan*)texture) + xpos+ypos*tex_rowspan;
if (bilinear)
{
__LICE_BilinearFilterI_2(&r,&g,&b,&a,rd,
ypos < texheight - 1 ? rd+tex_rowspan : ((LICE_pixel_chan *)texture)+xpos,
xpos < texwidth - 4 ? 4 : 4-texwidth,
iUL&65535,iVL&65535);
}
else
{
r=rd[LICE_PIXEL_R]; g=rd[LICE_PIXEL_G]; b=rd[LICE_PIXEL_B]; a=rd[LICE_PIXEL_A];
}
DoTextureCombine(texcomb, r,g,b,a, red,green,blue,alpha,texalpha,texalpha2);
}
_LICE_MakePixelClamp(gmemptr, red,green,blue,alpha);
}
#ifndef PLUSH_NO_TEXTURE
#include "pl_pf_tex.h"
#endif
#ifndef PLUSH_NO_MULTITEXTURE
#define PL_PF_MULTITEX
#include "pl_pf_tex.h"
#endif
template<class Comb> class PLSolidPutFace
{
public:
#ifndef PLUSH_NO_SOLIDGOURAUD
static void SolidGouraud(LICE_pixel *gmem, int swidth, pl_Face *TriFace, int alpha, pl_ZBuffer *zbuf, int zfb_width, bool zb_update)
{
pl_Float dZL=0, dZ1=0, dZ2=0;
pl_sInt32 dX1=0, dX2=0, C1[3], C2[3], dC1[3]={0}, dC2[3]={0}, dCL[3]={0}, C3[3];
PUTFACE_SORT();
int a;
for(a=0;a<3;a++)
{
C1[a] = (pl_sInt32) (TriFace->Shades[i0][a]*(1<<24));
C2[a] = (pl_sInt32) (TriFace->Shades[i1][a]*(1<<24));
C3[a] = (pl_sInt32) (TriFace->Shades[i2][a]*(1<<24));
}
pl_sInt32 X2,X1;
X2 = X1 = Scrx[i0];
pl_Float Z1 = TriFace->Scrz[i0];
pl_Float Z2 = TriFace->Scrz[i1];
pl_Float Z3 = TriFace->Scrz[i2];
pl_sInt32 Y0 = Scry[i0];
pl_sInt32 Y1 = Scry[i1];
pl_sInt32 Y2 = Scry[i2];
{
pl_sInt32 dY = Y2 - Y0;
if (dY) {
dX2 = (Scrx[i2] - X1) / dY;
for(a=0;a<3;a++) dC2[a] = (C3[a] - C1[a]) / dY;
dZ2 = (Z3 - Z1) / dY;
}
dY = Y1 - Y0;
if (dY) {
dX1 = (Scrx[i1] - X1) / dY;
for(a=0;a<3;a++)
dC1[a] = (C2[a] - C1[a]) / dY;
dZ1 = (Z2 - Z1) / dY;
if (dX2 < dX1) {
SWAP(dX2,dX1,pl_sInt32);
for(a=0;a<3;a++) SWAP(dC1[a],dC2[a],pl_sInt32);
SWAP(dZ1,dZ2,pl_Float);
stat = 2;
} else stat = 1;
Z2 = Z1;
C2[0] = C1[0];
C2[1] = C1[1];
C2[2] = C1[2];
} else {
if (Scrx[i1] > X1) {
X2 = Scrx[i1];
stat = 2|4;
} else {
for(a=0;a<3;a++) SWAP(C1[a],C2[a],pl_sInt32);
SWAP(Z1,Z2,pl_Float);
X1 = Scrx[i1];
stat = 1|8;
}
}
pl_sInt32 tmp = (dX1-dX2)*dY;
if (tmp) {
double v=(1<<XPOS_BITS)/(double)tmp;
for(a=0;a<3;a++)
dCL[a] = (pl_sInt32) (((dC1[a]-dC2[a])*dY)*v);
dZL = ((dZ1-dZ2)*dY)*v;
} else {
tmp = X2-X1;
if (tmp) {
double v=(1<<XPOS_BITS)/(double)tmp;
for(a=0;a<3;a++)
dCL[a] = (pl_sInt32) ((C2[a]-C1[a])*v);
dZL = (Z2-Z1)*v;
}
}
}
gmem += (Y0 * swidth);
zbuf += (Y0 * zfb_width);
while (Y0 < Y2) {
if (Y0 == Y1) {
pl_sInt32 dY = Y2 - Scry[i1];
if (dY) {
double v=1.0/dY;
dZ1 = (Z3-Z1)*v;
dC1[0] = (pl_sInt32) ((C3[0]-C1[0])*v);
dC1[1] = (pl_sInt32) ((C3[1]-C1[1])*v);
dC1[2] = (pl_sInt32) ((C3[2]-C1[2])*v);
DO_STAT_XDELTAS
}
}
pl_sInt32 XL1 = (X1+(1<<(XPOS_BITS-1)))>>XPOS_BITS;
pl_sInt32 XL2 = ((X2+(1<<(XPOS_BITS-1)))>>XPOS_BITS) - XL1;
if (XL2 > 0) {
gmem += XL1;
XL1 += XL2;
pl_sInt32 CL[3] = {C1[0],C1[1],C1[2]};
if (zbuf)
{
pl_Float ZL = Z1;
zbuf += XL1-XL2;
do {
if (*zbuf < ZL) {
if (zb_update) *zbuf = (pl_ZBuffer) ZL;
Comb::doPix((LICE_pixel_chan *)gmem,CL[0]>>16,CL[1]>>16,CL[2]>>16,255,alpha);
}
gmem++;
zbuf++;
ZL += dZL;
CL[0] += dCL[0];
CL[1] += dCL[1];
CL[2] += dCL[2];
} while (--XL2);
zbuf -= XL1;
}
else do {
Comb::doPix((LICE_pixel_chan *)gmem,CL[0]>>16,CL[1]>>16,CL[2]>>16,255,alpha);
gmem++;
CL[0] += dCL[0];
CL[1] += dCL[1];
CL[2] += dCL[2];
} while (--XL2);
gmem -= XL1;
}
gmem += swidth;
zbuf += zfb_width;
X1 += dX1;
X2 += dX2;
C1[0] += dC1[0];
C1[1] += dC1[1];
C1[2] += dC1[2];
Z1 += dZ1;
Y0++;
}
}
#endif
#ifndef PLUSH_NO_SOLIDFLAT
static void Solid(LICE_pixel *gmem, int swidth, pl_Face *TriFace, int alpha, pl_ZBuffer *zbuf, int zfb_width, bool zb_update)
{
pl_sInt32 dX1=0, dX2=0;
pl_Float dZL=0, dZ1=0, dZ2=0;
PUTFACE_SORT();
int col0 = (int) (TriFace->Shades[0][0]*255.0);
int col1 = (int) (TriFace->Shades[0][1]*255.0);
int col2 = (int) (TriFace->Shades[0][2]*255.0);
pl_sInt32 X1,X2;
X2 = X1 = Scrx[i0];
pl_sInt32 Y0 = Scry[i0];
pl_sInt32 Y1 = Scry[i1];
pl_sInt32 Y2 = Scry[i2];
pl_Float Z1 = TriFace->Scrz[i0];
pl_Float Z2 = TriFace->Scrz[i1];
pl_Float Z3 = TriFace->Scrz[i2];
{
pl_sInt32 dY = Y2-Y0;
if (dY) {
dX2 = (Scrx[i2] - X1) / dY;
dZ2 = (Z3 - Z1) / dY;
}
dY = Y1-Y0;
if (dY) {
dX1 = (Scrx[i1] - X1) / dY;
dZ1 = (Z2 - Z1) / dY;
if (dX2 < dX1) {
SWAP(dX1,dX2,pl_sInt32);
SWAP(dZ1,dZ2,pl_Float);
stat = 2;
} else stat = 1;
Z2 = Z1;
} else {
if (Scrx[i1] > X1) {
X2 = Scrx[i1];
stat = 2|4;
} else {
X1 = Scrx[i1];
SWAP(Z1,Z2,pl_Float);
stat = 1|8;
}
}
if (zbuf)
{
pl_sInt32 tmp=(dX1-dX2)*dY;
if (tmp) dZL = ((dZ1-dZ2)*dY)*(double)(1<<XPOS_BITS)/(double)tmp;
else {
tmp = X2-X1;
if (tmp) dZL = (Z2-Z1)*(double)(1<<XPOS_BITS)/tmp;
}
}
}
gmem += (Y0 * swidth);
zbuf += (Y0 * zfb_width);
while (Y0 < Y2) {
if (Y0 == Y1) {
pl_sInt32 dY = Y2 - Scry[i1];
if (dY) {
DO_STAT_XDELTAS
dZ1 = (Z3-Z1)/dY;
}
}
pl_sInt32 XL1 = (X1+(1<<(XPOS_BITS-1)))>>XPOS_BITS;
pl_sInt32 XL2 = ((X2+(1<<(XPOS_BITS-1)))>>XPOS_BITS) - XL1;
if (XL2 > 0) {
gmem += XL1;
XL1 += XL2;
if (zbuf)
{
pl_Float ZL = Z1;
zbuf += XL1-XL2;
do {
if (*zbuf < ZL) {
if (zb_update) *zbuf = (pl_ZBuffer) ZL;
Comb::doPix((LICE_pixel_chan *)gmem,col0,col1,col2,255,alpha);
}
gmem++;
zbuf++;
ZL += dZL;
} while (--XL2);
zbuf -= XL1;
}
else
{
do {
Comb::doPix((LICE_pixel_chan *)gmem,col0,col1,col2,255,alpha);
gmem++;
} while (--XL2);
}
gmem -= XL1;
}
gmem += swidth;
zbuf += zfb_width;
Z1 += dZ1;
X1 += dX1;
X2 += dX2;
Y0++;
}
}
#endif
};
void pl_Cam::PutFace(pl_Face *TriFace)
{
LICE_pixel *gmem = m_fBuffer.m_buf;
if (WDL_NOT_NORMALLY(!gmem)) return;
int zfb_width = 0;
int zBufferable = TriFace->Material->zBufferable;
pl_ZBuffer *zb = NULL;
if (zBufferable &&
zBuffer.GetSize() &&
WDL_NORMALLY(zBuffer.GetSize() >= m_fBuffer.m_w*m_fBuffer.m_h)
)
{
zfb_width = m_fBuffer.m_w;
zb = zBuffer.Get();
}
int swidth = m_fBuffer.m_span;
if (m_fBuffer.m_flipped)
{
gmem += swidth*(m_fBuffer.m_h-1);
swidth=-swidth;
}
pl_Mat *mat=TriFace->Material;
#ifndef PLUSH_NO_MULTITEXTURE
#ifndef PLUSH_NO_TEXTURE
if (mat->Texture&&mat->Texture2)
#else
#ifndef PLUSH_NO_SOLIDGOURAUD
if (mat->Texture||mat->Texture2)
#endif
#endif
{
pl_Float texsc[4];
memcpy(texsc,mat->TexScaling,sizeof(mat->TexScaling));
memcpy(texsc+2,mat->Tex2Scaling,sizeof(mat->Tex2Scaling));
int tidx = mat->TexMapIdx;
if (tidx<0 || tidx>=PLUSH_MAX_MAPCOORDS)tidx=PLUSH_MAX_MAPCOORDS-1;
int tidx2 = mat->Tex2MapIdx;
if (tidx2<0 || tidx2>=PLUSH_MAX_MAPCOORDS)tidx2=PLUSH_MAX_MAPCOORDS-1;
PLMTexTri(gmem,swidth,TriFace,zb,zfb_width,zBufferable!=2,(int) (mat->SolidOpacity*256.0),mat->SolidCombineMode,
mat->Texture,texsc,(int) (mat->TexOpacity*256.0),mat->TexCombineMode,tidx,
mat->Texture2,(int) (mat->Tex2Opacity*256.0),mat->Tex2CombineMode,tidx2
);
return;
}
#endif
#ifndef PLUSH_NO_TEXTURE
#ifndef PLUSH_NO_SOLIDGOURAUD
if (mat->Texture||mat->Texture2)
#endif
{
LICE_IBitmap *tex=mat->Texture ? mat->Texture : mat->Texture2;
int talpha = (int) (mat->Texture ? mat->TexOpacity*256.0 : mat->Tex2Opacity*256.0);
int tcomb = (int) (mat->Texture ? mat->TexCombineMode : mat->Tex2CombineMode);
int tidx = (mat->Texture ? mat->TexMapIdx: mat->Tex2MapIdx);
if (tidx<0 || tidx>=PLUSH_MAX_MAPCOORDS)tidx=PLUSH_MAX_MAPCOORDS-1;
pl_Float texsc[2];
memcpy(texsc,mat->Texture ? mat->TexScaling : mat->Tex2Scaling,sizeof(texsc));
PLTexTri(gmem,swidth,TriFace,zb,zfb_width,zBufferable!=2,(int) (mat->SolidOpacity*256.0),mat->SolidCombineMode,tex,texsc,talpha,tcomb,tidx);
return;
}
#endif
int alpha=(int) (mat->SolidOpacity*256.0);
if (!alpha) return;
#ifndef PLUSH_NO_SOLIDGOURAUD
#ifndef PLUSH_NO_SOLIDFLAT
if (mat->Smoothing)
#endif
{
#define __LICE__ACTION(comb) PLSolidPutFace<comb>::SolidGouraud(gmem,swidth,TriFace,alpha,zb,zfb_width, zBufferable!=2);
__LICE_ACTION_CONSTANTALPHA(mat->SolidCombineMode,alpha,true);
#undef __LICE__ACTION
return;
}
#endif
#ifndef PLUSH_NO_SOLIDFLAT
#define __LICE__ACTION(comb) PLSolidPutFace<comb>::Solid(gmem,swidth,TriFace,alpha,zb,zfb_width, zBufferable!=2);
__LICE_ACTION_CONSTANTALPHA(mat->SolidCombineMode,alpha,true);
#undef __LICE__ACTION
#endif // PLUSH_NO_SOLIDFLAT
}

View File

@@ -0,0 +1,347 @@
/******************************************************************************
Plush Version 1.2
read_3ds.c
3DS Object Reader
Copyright (c) 1996-2000, Justin Frankel
******************************************************************************/
#include "plush.h"
typedef struct
{
pl_uInt16 id;
void (*func)(pl_uChar *ptr, pl_uInt32 p);
} _pl_3DSChunk;
static pl_Obj *obj;
static pl_Obj *bobj;
static pl_Obj *lobj;
static pl_sInt16 currentobj;
static pl_Mat *_m;
static pl_Float _pl3DSReadFloat(pl_uChar **ptr);
static pl_uInt32 _pl3DSReadDWord(pl_uChar **ptr);
static pl_uInt16 _pl3DSReadWord(pl_uChar **ptr);
static void _pl3DSChunkReader(pl_uChar *ptr, int len);
static void _pl3DSRGBFReader(pl_uChar *f, pl_uInt32 p);
static void _pl3DSRGBBReader(pl_uChar *f, pl_uInt32 p);
static int _pl3DSASCIIZReader(pl_uChar *ptr, pl_uInt32 p, char *as);
static void _pl3DSObjBlockReader(pl_uChar *ptr, pl_uInt32 p);
static void _pl3DSTriMeshReader(pl_uChar *f, pl_uInt32 p);
static void _pl3DSVertListReader(pl_uChar *f, pl_uInt32 p);
static void _pl3DSFaceListReader(pl_uChar *f, pl_uInt32 p);
static void _pl3DSFaceMatReader(pl_uChar *f, pl_uInt32 p);
static void MapListReader(pl_uChar *f, pl_uInt32 p);
static pl_sInt16 _pl3DSFindChunk(pl_uInt16 id);
static _pl_3DSChunk _pl3DSChunkNames[] = {
{0x4D4D,NULL}, /* Main */
{0x3D3D,NULL}, /* Object Mesh */
{0x4000,_pl3DSObjBlockReader},
{0x4100,_pl3DSTriMeshReader},
{0x4110,_pl3DSVertListReader},
{0x4120,_pl3DSFaceListReader},
{0x4130,_pl3DSFaceMatReader},
{0x4140,MapListReader},
{0xAFFF,NULL}, /* Material */
{0xA010,NULL}, /* Ambient */
{0xA020,NULL}, /* Diff */
{0xA030,NULL}, /* Specular */
{0xA200,NULL}, /* Texture */
{0x0010,_pl3DSRGBFReader},
{0x0011,_pl3DSRGBBReader},
};
pl_Obj *plRead3DSObjFromFile(char *fn, pl_Mat *m)
{
FILE *f = fopen(fn, "rb");
if (!f) return 0;
fseek(f, 0, 2);
pl_uInt32 p = ftell(f);
rewind(f);
WDL_HeapBuf buf;
buf.Resize(p);
int s = fread(buf.Get(), 1, p, f);
fclose(f);
if(!s) return 0;
return plRead3DSObj(buf.Get(), s, m);
}
pl_Obj *plRead3DSObjFromResource(HINSTANCE hInst, int resid, pl_Mat *m)
{
#ifdef _WIN32
HRSRC hResource = FindResource(hInst, MAKEINTRESOURCE(resid), "3DS");
if(!hResource) return NULL;
DWORD imageSize = SizeofResource(hInst, hResource);
if(imageSize < 6) return NULL;
HGLOBAL res = LoadResource(hInst, hResource);
const void* pResourceData = LockResource(res);
if(!pResourceData) return NULL;
unsigned char *data = (unsigned char *)pResourceData;
pl_Obj *o = plRead3DSObj(data, imageSize, m);
DeleteObject(res);
return o;
#else
return 0;
#endif
}
pl_Obj *plRead3DSObj(void *ptr, int size, pl_Mat *m)
{
_m = m;
obj = bobj = lobj = 0;
currentobj = 0;
_pl3DSChunkReader((pl_uChar *)ptr, size);
return bobj;
}
static pl_Float _pl3DSReadFloat(pl_uChar **ptr) {
pl_uInt32 *i;
pl_IEEEFloat32 c;
i = (pl_uInt32 *) &c;
*i = _pl3DSReadDWord(ptr);
return ((pl_Float) c);
}
static pl_uInt32 _pl3DSReadDWord(pl_uChar **ptr)
{
pl_uInt32 r;
pl_uChar *p = *ptr;
r = *p++;
r |= (*p++)<<8;
r |= (*p++)<<16;
r |= (*p++)<<24;
*ptr += 4;
return r;
}
static pl_uInt16 _pl3DSReadWord(pl_uChar **ptr)
{
pl_uInt16 r;
pl_uChar *p = *ptr;
r = *p++;
r |= (*p++)<<8;
*ptr += 2;
return r;
}
static void _pl3DSRGBFReader(pl_uChar *f, pl_uInt32 p)
{
pl_Float c[3];
if(p < 3*4) return;
c[0] = _pl3DSReadFloat(&f);
c[1] = _pl3DSReadFloat(&f);
c[2] = _pl3DSReadFloat(&f);
}
static void _pl3DSRGBBReader(pl_uChar *f, pl_uInt32 p)
{
unsigned char c[3];
if(p < 3) return;
memcpy(c, f, sizeof(c));
}
static int _pl3DSASCIIZReader(pl_uChar *ptr, pl_uInt32 p, char *as)
{
int l = 0;
while (*ptr && p>0)
{
if(as) *as++ = *ptr;
ptr++;
l++;
p--;
}
if(as) *as = 0;
return l+1;
}
static void _pl3DSObjBlockReader(pl_uChar *ptr, pl_uInt32 p)
{
int l = _pl3DSASCIIZReader(ptr, p, 0);
ptr += l;
p -= l;
_pl3DSChunkReader(ptr, p);
}
static void _pl3DSTriMeshReader(pl_uChar *ptr, pl_uInt32 p)
{
pl_uInt32 i;
pl_Face *face;
obj = new pl_Obj;
_pl3DSChunkReader(ptr, p);
i = obj->Faces.GetSize();
face = obj->Faces.Get();
while (i--)
{
pl_Vertex *vp=obj->Vertices.Get();
pl_Vertex *fVertices[3] = {
vp+face->VertexIndices[0],
vp+face->VertexIndices[1],
vp+face->VertexIndices[2],
};
face->MappingU[0][0] = fVertices[0]->xformedx;
face->MappingV[0][0] = fVertices[0]->xformedy;
face->MappingU[0][1] = fVertices[1]->xformedx;
face->MappingV[0][1] = fVertices[1]->xformedy;
face->MappingU[0][2] = fVertices[2]->xformedx;
face->MappingV[0][2] = fVertices[2]->xformedy;
face++;
}
obj->CalculateNormals();
if (currentobj == 0)
{
currentobj = 1;
lobj = bobj = obj;
}
else
{
lobj->Children.Add(obj);
lobj = obj;
}
}
static void _pl3DSVertListReader(pl_uChar *f, pl_uInt32 p)
{
pl_uInt16 nv;
pl_Vertex *v;
int len = (int)p;
nv = _pl3DSReadWord(&f);
len -= 2;
if(len <= 0) return;
obj->Vertices.Resize(nv);
v = obj->Vertices.Get();
while (nv--)
{
memset(v,0,sizeof(pl_Vertex));
v->x = _pl3DSReadFloat(&f);
v->y = _pl3DSReadFloat(&f);
v->z = _pl3DSReadFloat(&f);
len -= 3*4;
if(len < 0) return;
v++;
}
}
static void _pl3DSFaceListReader(pl_uChar *f, pl_uInt32 p)
{
pl_uInt16 nv;
pl_uInt16 c[3];
pl_uInt16 flags;
pl_Face *face;
int len = (int)p;
nv = _pl3DSReadWord(&f);
len -= 2;
if(len <= 0) return;
obj->Faces.Resize(nv);
face = obj->Faces.Get();
while (nv--)
{
memset(face,0,sizeof(pl_Face));
c[0] = _pl3DSReadWord(&f);
c[1] = _pl3DSReadWord(&f);
c[2] = _pl3DSReadWord(&f);
flags = _pl3DSReadWord(&f);
len -= 4*2;
if(len < 0) return;
face->VertexIndices[0] = (c[0]&0x0000FFFF);
face->VertexIndices[1] = (c[1]&0x0000FFFF);
face->VertexIndices[2] = (c[2]&0x0000FFFF);
face->Material = _m;
face++;
}
if(len) _pl3DSChunkReader(f, len);
}
static void _pl3DSFaceMatReader(pl_uChar *ptr, pl_uInt32 p)
{
pl_uInt16 n, nf;
int l = _pl3DSASCIIZReader(ptr, p, 0);
ptr += l;
p -= l;
n = _pl3DSReadWord(&ptr);
while (n--)
{
nf = _pl3DSReadWord(&ptr);
}
}
static void MapListReader(pl_uChar *f, pl_uInt32 p)
{
pl_uInt16 nv;
pl_Float c[2];
pl_Vertex *v;
int len = (int) p;
nv = _pl3DSReadWord(&f);
len -= 2;
v = obj->Vertices.Get();
if (nv == obj->Vertices.GetSize()) while (nv--)
{
c[0] = _pl3DSReadFloat(&f);
c[1] = _pl3DSReadFloat(&f);
len -= 2*4;
if (len < 0) return;
v->xformedx = c[0];
v->xformedy = c[1];
v++;
}
}
static pl_sInt16 _pl3DSFindChunk(pl_uInt16 id)
{
pl_sInt16 i;
for (i = 0; i < sizeof(_pl3DSChunkNames)/sizeof(_pl3DSChunkNames[0]); i++)
if (id == _pl3DSChunkNames[i].id) return i;
return -1;
}
static void _pl3DSChunkReader(pl_uChar *ptr, int len)
{
pl_uInt32 hlen;
pl_uInt16 hid;
pl_sInt16 n;
while (len > 0)
{
hid = _pl3DSReadWord(&ptr);
len -= 2;
if(len <= 0) return;
hlen = _pl3DSReadDWord(&ptr);
len -= 4;
if(len <= 0) return;
if (hlen == 0) return;
hlen -= 6;
n = _pl3DSFindChunk(hid);
if (n < 0)
{
ptr += hlen;
len -= hlen;
}
else
{
pl_uChar *p = ptr;
if (_pl3DSChunkNames[n].func != NULL)
_pl3DSChunkNames[n].func(p, hlen);
else
_pl3DSChunkReader(p, hlen);
ptr += hlen;
len -= hlen;
}
}
}

View File

@@ -0,0 +1,181 @@
/******************************************************************************
Plush Version 1.2
read_cob.c
ASCII COB Object Reader
Copyright (c) 1996-2000, Justin Frankel
******************************************************************************/
#include "plush.h"
#define PL_COB_MAX_LINELENGTH 1024
pl_Obj *plReadCOBObj(char *fn, pl_Mat *mat) {
FILE *fp = fopen(fn,"rt");
int p1,m1,p2,m2,p3,m3;
char temp_string[PL_COB_MAX_LINELENGTH];
float TransMatrix[4][4];
pl_Obj *obj;
pl_sInt32 x,i2;
int numVertices, numMappingVertices, numFaces, i;
pl_Float *MappingVertices = 0;
if (!fp) return 0;
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
if (memcmp("Caligari",temp_string,8)) { fclose(fp); return 0; }
do {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
} while (!feof(fp) && memcmp("Transform",temp_string,9));
if (feof(fp)) { fclose(fp); return 0; }
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
sscanf(temp_string,"%f %f %f %f",
&TransMatrix[0][0],&TransMatrix[0][1],&TransMatrix[0][2],&TransMatrix[0][3]);
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
sscanf(temp_string,"%f %f %f %f",
&TransMatrix[1][0],&TransMatrix[1][1],&TransMatrix[1][2],&TransMatrix[1][3]);
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
sscanf(temp_string,"%f %f %f %f",
&TransMatrix[2][0],&TransMatrix[2][1],&TransMatrix[2][2],&TransMatrix[2][3]);
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
sscanf(temp_string,"%f %f %f %f",
&TransMatrix[3][0],&TransMatrix[3][1],&TransMatrix[3][2],&TransMatrix[3][3]);
do {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
} while (!feof(fp) && memcmp("World Vertices",temp_string,12));
if (feof(fp) || sscanf(temp_string,"World Vertices %d",&numVertices) != 1)
{ fclose(fp); return 0; }
rewind(fp);
do {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
} while (!feof(fp) && memcmp("Texture Vertices",temp_string,16));
if (feof(fp) ||
sscanf(temp_string,"Texture Vertices %d",&numMappingVertices) != 1) {
fclose(fp); return 0;
}
rewind(fp);
do {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
} while (!feof(fp) && memcmp("Faces",temp_string,5));
if (feof(fp) || sscanf(temp_string,"Faces %d",&numFaces) != 1) {
fclose(fp); return 0;
}
for (x = numFaces; x; x--) {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
if (feof(fp) || sscanf(temp_string+4," verts %d",&i) != 1 || i < 3) {
fclose(fp);
return 0;
}
numFaces += i-3;
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
}
obj = new pl_Obj(numVertices,numFaces);
if (!obj) { fclose(fp); return 0; }
rewind(fp);
do {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
} while (!feof(fp) && memcmp("World Vertices",temp_string,12));
if (feof(fp)) { delete obj; fclose(fp); return 0; }
for (x = 0; x < numVertices; x ++) {
float xp, yp, zp;
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
if (feof(fp) ||
sscanf(temp_string,"%f %f %f", &xp, &yp, &zp) != 3) {
delete obj; fclose(fp); return 0;
}
obj->Vertices.Get()[x].x = (TransMatrix[0][0]*xp+TransMatrix[0][1]*yp+
TransMatrix[0][2]*zp+TransMatrix[0][3]);
obj->Vertices.Get()[x].y = (TransMatrix[1][0]*xp+TransMatrix[1][1]*yp+
TransMatrix[1][2]*zp+TransMatrix[1][3]);
obj->Vertices.Get()[x].z = (TransMatrix[2][0]*xp+TransMatrix[2][1]*yp+
TransMatrix[2][2]*zp+TransMatrix[2][3]);
}
rewind(fp);
do {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
} while (!feof(fp) && memcmp("Texture Vertices",temp_string,16));
if (!feof(fp)) {
MappingVertices = (pl_Float *)
malloc(sizeof(pl_Float ) * numMappingVertices * 2);
if (MappingVertices) {
for (x = 0; x < numMappingVertices; x ++) {
float p1, p2;
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
if (feof(fp) || sscanf(temp_string,"%f %f", &p1, &p2) != 2) {
free(MappingVertices); delete obj; fclose(fp); return 0;
}
MappingVertices[x*2] = p1;
MappingVertices[x*2+1] = p2;
}
}
}
rewind(fp);
do {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
} while (!feof(fp) && memcmp("Faces",temp_string,5));
if (feof(fp)) {
if (MappingVertices) free(MappingVertices);
delete obj; fclose(fp); return 0;
}
for (x = 0; x < numFaces; x ++) {
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
sscanf(temp_string+4," verts %d",&i);
fgets(temp_string,PL_COB_MAX_LINELENGTH,fp);
if (i == 3) {
if (feof(fp) || sscanf(temp_string,"<%d,%d> <%d,%d> <%d,%d>",
&p3,&m3,&p2,&m2,&p1,&m1) != 6) {
if (MappingVertices) free(MappingVertices);
delete obj; fclose(fp); return 0;
}
obj->Faces.Get()[x].VertexIndices[0] = p1;
obj->Faces.Get()[x].VertexIndices[1] = p2;
obj->Faces.Get()[x].VertexIndices[2] = p3;
if (MappingVertices) {
obj->Faces.Get()[x].MappingU[0][0] = MappingVertices[m1*2];
obj->Faces.Get()[x].MappingV[0][0] = MappingVertices[m1*2+1];
obj->Faces.Get()[x].MappingU[0][1] = MappingVertices[m2*2];
obj->Faces.Get()[x].MappingV[0][1] = MappingVertices[m2*2+1];
obj->Faces.Get()[x].MappingU[0][2] = MappingVertices[m3*2];
obj->Faces.Get()[x].MappingV[0][2] = MappingVertices[m3*2+1];
}
obj->Faces.Get()[x].Material = mat;
} else {
int p[16],m[16];
if (feof(fp)) {
if (MappingVertices) free(MappingVertices);
delete obj; fclose(fp); return 0;
}
sscanf(temp_string,
"<%d,%d> <%d,%d> <%d,%d> <%d,%d> "
"<%d,%d> <%d,%d> <%d,%d> <%d,%d> "
"<%d,%d> <%d,%d> <%d,%d> <%d,%d> "
"<%d,%d> <%d,%d> <%d,%d> <%d,%d> ",
p+0,m+0,p+1,m+1,p+2,m+2,p+3,m+3,
p+4,m+4,p+5,m+5,p+6,m+6,p+7,m+7,
p+8,m+8,p+9,m+9,p+10,m+10,p+11,m+11,
p+12,m+12,p+13,m+13,p+14,m+14,p+15,m+15);
for (i2 = 1; i2 < (i-1); i2 ++) {
obj->Faces.Get()[x].VertexIndices[0] = p[0];
obj->Faces.Get()[x].VertexIndices[1] = p[i2+1];
obj->Faces.Get()[x].VertexIndices[2] = p[i2];
if (MappingVertices) {
obj->Faces.Get()[x].MappingU[0][0] = MappingVertices[m[0]*2];
obj->Faces.Get()[x].MappingV[0][0] = MappingVertices[m[0]*2+1];
obj->Faces.Get()[x].MappingU[0][1] = MappingVertices[m[i2+1]*2];
obj->Faces.Get()[x].MappingV[0][1] = MappingVertices[m[i2+1]*2+1];
obj->Faces.Get()[x].MappingU[0][2] = MappingVertices[m[i2]*2];
obj->Faces.Get()[x].MappingV[0][2] = MappingVertices[m[i2]*2+1];
}
obj->Faces.Get()[x].Material = mat;
x++;
}
x--;
}
}
if (MappingVertices) free(MappingVertices);
obj->CalculateNormals();
fclose(fp);
return obj;
}

View File

@@ -0,0 +1,69 @@
/******************************************************************************
Plush Version 1.2
read_jaw.c
Jaw3D Object Reader
Copyright (c) 1996-2000, Justin Frankel
*******************************************************************************
Notes on .JAW files:
This is a file format created by Jawed Karim for Jaw3D
(http://jaw3d.home.ml.org).
-- updated 11/6/00 - www.jawed.com
It is very simple, and lets one easily create ones own models using only
a text editor. The format is pretty simple:
The first line must be "Light: (x,y,z)" where x,y, and z are the x y and
z components of the lightsource vector (I think ;)
A series of lines, numbered 0 to n, in the format of
"i: x y z", where i is the vertex number (which should be listed in
order, and x y and z are the coordinates of that vertex.
A series of lines, having the format "tri a, b, c" where a b and c are
the vertices that the face uses. It is unclear at this time which
way the vertices are listed (ccw or cw), so just make em consistent
and you can always use plFlipObjectNormals() on the loaded object.
That is it! (I told ya it was simple).
******************************************************************************/
#include "plush.h"
pl_Obj *plReadJAWObj(char *filename, pl_Mat *m) {
FILE *jawfile;
pl_Obj *obj;
pl_uInt32 i;
pl_sInt crap;
char line[256];
pl_uInt32 total_points = 0, total_polys = 0;
if ((jawfile = fopen(filename, "r")) == NULL) return 0;
fgets(line, 256, jawfile); /* Ignores lightsource info */
while (fgets(line, 256, jawfile) != NULL)
if (strstr(line, ":") != NULL) total_points++;
rewind(jawfile); fgets(line, 256, jawfile);
while (fgets(line, 256, jawfile) != NULL)
if (strstr(line, "tri") != NULL) total_polys++;
rewind(jawfile); fgets(line, 256, jawfile);
obj = new pl_Obj(total_points,total_polys);
i = 0;
while (fgets(line, 256, jawfile) != NULL) if (strstr(line, ":") != NULL) {
float x, y, z;
sscanf(line, "%d: %f %f %f",&crap,&x,&y,&z);
obj->Vertices.Get()[i].x = (pl_Float) x;
obj->Vertices.Get()[i].y = (pl_Float) y;
obj->Vertices.Get()[i].z = (pl_Float) z;
i++;
}
rewind(jawfile); fgets(line, 256, jawfile);
i = 0;
while (fgets(line, 256, jawfile) != NULL) if (strstr(line, "tri") != NULL) {
pl_uInt32 a,b,c;
sscanf(line, "tri %ld, %ld, %ld", &a, &b, &c);
obj->Faces.Get()[i].VertexIndices[0] = a;
obj->Faces.Get()[i].VertexIndices[1] = c;
obj->Faces.Get()[i].VertexIndices[2] = b;
obj->Faces.Get()[i].Material = m;
i++;
}
fclose(jawfile);
obj->CalculateNormals();
return obj;
}

View File

@@ -0,0 +1,50 @@
/******************************************************************************
Plush Version 1.2
spline.c
n-th Dimensional Spline Interpolator
Copyright (c) 1996-2000, Justin Frankel
******************************************************************************/
#include "plush.h"
void pl_Spline::GetPoint(pl_Float frame, pl_Float *out) {
pl_sInt32 i, i_1, i0, i1, i2;
pl_Float time1,time2,time3;
pl_Float t1,t2,t3,t4,u1,u2,u3,u4,v1,v2,v3;
pl_Float a,b,c,d;
int numKeys=keys.GetSize();
pl_Float *keyptrs = keys.Get();
a = (1-tens)*(1+cont)*(1+bias);
b = (1-tens)*(1-cont)*(1-bias);
c = (1-tens)*(1-cont)*(1+bias);
d = (1-tens)*(1+cont)*(1-bias);
v1 = t1 = -a / 2.0; u1 = a;
u2 = (-6-2*a+2*b+c)/2.0; v2 = (a-b)/2.0; t2 = (4+a-b-c) / 2.0;
t3 = (-4+b+c-d) / 2.0;
u3 = (6-2*b-c+d)/2.0;
v3 = b/2.0;
t4 = d/2.0; u4 = -t4;
i0 = (pl_uInt) frame;
i_1 = i0 - 1;
while (i_1 < 0) i_1 += numKeys;
i1 = i0 + 1;
while (i1 >= numKeys) i1 -= numKeys;
i2 = i0 + 2;
while (i2 >= numKeys) i2 -= numKeys;
time1 = frame - (pl_Float) ((pl_uInt) frame);
time2 = time1*time1;
time3 = time2*time1;
i0 *= keyWidth;
i1 *= keyWidth;
i2 *= keyWidth;
i_1 *= keyWidth;
for (i = 0; i < keyWidth; i ++) {
a = t1*keyptrs[i+i_1]+t2*keyptrs[i+i0]+t3*keyptrs[i+i1]+t4*keyptrs[i+i2];
b = u1*keyptrs[i+i_1]+u2*keyptrs[i+i0]+u3*keyptrs[i+i1]+u4*keyptrs[i+i2];
c = v1*keyptrs[i+i_1]+v2*keyptrs[i+i0]+v3*keyptrs[i+i1];
*out++ = a*time3 + b*time2 + c*time1 + keyptrs[i+i0];
}
}

View File

@@ -0,0 +1,607 @@
/******************************************************************************
plush.h
PLUSH 3D VERSION 2.0 MAIN HEADER
Copyright (c) 1996-2000 Justin Frankel
Copyright (c) 1998-2000 Nullsoft, Inc.
Copyright (c) 2008 Cockos Incorporated
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
******************************************************************************/
#ifndef _PLUSH_H_
#define _PLUSH_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "../lice/lice.h" // using LICE for images
#include "../ptrlist.h"
#include "../wdltypes.h"
typedef float pl_ZBuffer; /* z-buffer type (must be float) */
typedef double pl_Float; /* General floating point */
typedef float pl_IEEEFloat32; /* IEEE 32 bit floating point */
typedef signed int pl_sInt32; /* signed 32 bit integer */
typedef unsigned int pl_uInt32; /* unsigned 32 bit integer */
typedef signed short int pl_sInt16; /* signed 16 bit integer */
typedef unsigned short int pl_uInt16; /* unsigned 16 bit integer */
typedef signed int pl_sInt; /* signed optimal integer */
typedef unsigned int pl_uInt; /* unsigned optimal integer */
typedef bool pl_Bool; /* boolean */
typedef unsigned char pl_uChar; /* unsigned 8 bit integer */
typedef signed char pl_sChar; /* signed 8 bit integer */
/* pi! */
#define PL_PI 3.141592653589793238
/* Utility min() and max() functions */
#define plMin(x,y) (( ( x ) > ( y ) ? ( y ) : ( x )))
#define plMax(x,y) (( ( x ) < ( y ) ? ( y ) : ( x )))
/*
** Light modes. Used with plLight.Type or plLightSet().
** Note that PL_LIGHT_POINT_ANGLE assumes no falloff and uses the angle between
** the light and the point, PL_LIGHT_POINT_DISTANCE has falloff with proportion
** to distance**2 (see plLightSet() for setting it), PL_LIGHT_POINT does both.
*/
#define PL_LIGHT_NONE (0x0)
#define PL_LIGHT_VECTOR (0x1)
#define PL_LIGHT_POINT (0x2|0x4)
#define PL_LIGHT_POINT_DISTANCE (0x2)
#define PL_LIGHT_POINT_ANGLE (0x4)
#define PLUSH_MAX_MAPCOORDS 3 // 2 + envmap slot
class pl_Mat
{
public:
pl_Mat()
{
memset(Ambient,0,sizeof(Ambient));
Diffuse[0]=Diffuse[1]=Diffuse[2]=1.0;
SolidOpacity=1.0;
SolidCombineMode= LICE_BLIT_MODE_COPY;
Texture=NULL;
TexCombineMode = LICE_BLIT_MODE_ADD; //LICE_BLIT_USE_SOURCE_ALPHA?
TexOpacity=1.0;
TexScaling[0]=TexScaling[1]=1.0;
TexMapIdx=0;
Texture2=NULL;
Tex2CombineMode = LICE_BLIT_MODE_ADD;
Tex2Opacity=1.0;
Tex2Scaling[0]=Tex2Scaling[1]=1.0;
Tex2MapIdx=-1;
FadeDist=0.0;
Smoothing=Lightable=true;
zBufferable=1;
PerspectiveCorrect=16;
BackfaceCull=true;
BackfaceIllumination=0.0;
cachedTexture=cachedTexture2=0;
cachesInvalid=true;
}
~pl_Mat()
{
delete cachedTexture;
delete cachedTexture2;
}
pl_Bool Smoothing; // smoothing of lighting
pl_Bool Lightable; // affected by lights
pl_uChar zBufferable; /* Can this material be Z-buffered? 2=yes, but does not update Z buffer */
pl_uChar PerspectiveCorrect; /* Correct texture perspective every n pixels */
pl_Float FadeDist WDL_FIXALIGN; /* For distance fading, distance at which intensity is 0. set to 0.0 for no distance shading */
pl_Bool BackfaceCull; /* Are backfacing polys drawn? */
pl_Float BackfaceIllumination WDL_FIXALIGN; /* Illuminated by lights behind them, and by how much of a factor? */
// colors
pl_Float Ambient[3]; /* RGB of surface (0-1 is a good range) */
pl_Float Diffuse[3]; /* RGB of diffuse (0-1 is a good range) */
pl_Float SolidOpacity;
int SolidCombineMode; /* LICE combine mode for first pass (color), default should be replace (or add-black for transparent) */
// textures
LICE_IBitmap *Texture; /* Texture map (not owned by Material but a reference)*/
pl_Float TexScaling[2] WDL_FIXALIGN; /* Texture map scaling */
pl_Float TexOpacity;
int TexCombineMode; /* Texture combine mode (generally should be additive) */
int TexMapIdx; // -1 for env
LICE_IBitmap *Texture2;
pl_Float Tex2Scaling[2] WDL_FIXALIGN;
pl_Float Tex2Opacity;
int Tex2CombineMode;
int Tex2MapIdx; // -1 for env
void InvalidateTextureCaches() { cachesInvalid=true; } // call this if you change Texture or Texture2 after rendering
private:
bool cachesInvalid;
LICE_IBitmap *cachedTexture,*cachedTexture2; // these may need to be LICE_GL_MemBitmaps etc
} WDL_FIXALIGN;
struct pl_Vertex {
pl_Float x, y, z; /* Vertex coordinate (objectspace) */
pl_Float nx, ny, nz; /* Unit vertex normal (objectspace) */
pl_Float xformedx, xformedy, xformedz; /* Transformed vertex coordinate (cameraspace) */
pl_Float xformednx, xformedny, xformednz; /* Transformed unit vertex normal (cameraspace) */
};
struct pl_Face {
pl_Mat *Material; /* Material of triangle */
int VertexIndices[3]; /* Vertices of triangle */
pl_Float nx WDL_FIXALIGN;
pl_Float ny;
pl_Float nz; /* Normal of triangle (object space) */
pl_Float MappingU[PLUSH_MAX_MAPCOORDS][3], MappingV[PLUSH_MAX_MAPCOORDS][3]; /* Texture mapping coordinates */
pl_Float sLighting[3]; /* Face static lighting. Should usually be 0.0 */
pl_Float vsLighting[3][3]; /* Vertex static lighting. Should usually be 0.0 */
// calculated:
pl_Float Shades[3][3]; /* colors (first 3 used for flat, all for Gouraud) */
pl_Float Scrx[3], Scry[3]; /* Projected screen coordinates */
pl_Float Scrz[3]; /* Projected 1/Z coordinates */
};
class pl_Obj {
public:
pl_Obj(int nv=0, int nf=0)
{
if (nv) memset(Vertices.Resize(nv),0,nv*sizeof(pl_Vertex));
if (nf) memset(Faces.Resize(nf),0,nf*sizeof(pl_Face));
GenMatrix=true;
Xp=Yp=Zp=Xa=Ya=Za=0.0;
}
~pl_Obj() { Children.Empty(true); }
pl_Obj *Clone();
void Scale(pl_Float sc);
void Stretch(pl_Float x, pl_Float y, pl_Float z); // scales but preserves normals
void Translate(pl_Float x, pl_Float y, pl_Float z);
void FlipNormals();
void SetMaterial(pl_Mat *m, pl_Bool recurse=true);
void CalculateNormals();
pl_Float Xp, Yp, Zp, Xa, Ya, Za; /* Position and rotation of object:
Note: rotations are around X then Y then Z. Measured in degrees */
pl_Float Matrix[16]; /* Transformation matrix */
pl_Float RotMatrix[16]; /* Rotation-only, for normals */
WDL_TypedBuf<pl_Vertex> Vertices;
WDL_TypedBuf<pl_Face> Faces;
WDL_PtrList<pl_Obj> Children;
pl_Bool GenMatrix; /* Generate Matrix from X-Z* if set */
};
class pl_Spline {
public:
pl_Spline() { cont=1.0; bias=0.3; tens=0.3; keyWidth=1; }
~pl_Spline () { }
void GetPoint(pl_Float frame, pl_Float *out);
WDL_TypedBuf<pl_Float> keys; /* Key data, keyWidth*numKeys */
pl_sInt keyWidth; /* Number of floats per key */
pl_Float cont WDL_FIXALIGN; /* Continuity. Should be -1.0 -> 1.0 */
pl_Float bias; /* Bias. -1.0 -> 1.0 */
pl_Float tens; /* Tension. -1.0 -> 1.0 */
};
class pl_Light {
public:
pl_Light() { Type = PL_LIGHT_VECTOR; Xp=Yp=0.0; Zp=1.0; Intensity[0]=Intensity[1]=Intensity[2]=1.0; }
~pl_Light() { }
/*
Set() sets up a light:
mode: the mode of the light (PL_LIGHT_*)
x,y,z: either the position of the light (PL_LIGHT_POINT*) or the angle
in degrees of the light (PL_LIGHT_VECTOR)
intensity: the intensity of the light (0.0-1.0)
halfDist: the distance at which PL_LIGHT_POINT_DISTANCE is 1/2 intensity
*/
void 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);
// privatestuff
pl_uChar Type; /* Type of light: PL_LIGHT_* */
pl_Float Xp WDL_FIXALIGN;
pl_Float Yp, Zp; /* If Type=PL_LIGHT_POINT*,
this is Position (PL_LIGHT_POINT_*),
otherwise if PL_LIGHT_VECTOR,
Unit vector */
pl_Float Intensity[3]; /* Intensity. 0.0 is off, 1.0 is full */
pl_Float HalfDistSquared; /* Distance squared at which
PL_LIGHT_POINT_DISTANCE is 50% */
};
class pl_Cam {
public:
pl_Cam() : m_fBuffer(NULL,0,0,0,false)
{
m_lastFBScaling=256;
m_lastFBWidth=m_lastFBHeight=0;
Fov=90.0;
AspectRatio=1.0;
Sort=1;
ClipBack=-1.0;
CenterX=CenterY=0;
X=Y=Z=0.0;
WantZBuffer=false;
Pitch=Pan=Roll=0.0;
GenMatrix = true;
}
~pl_Cam()
{
}
void SetTarget(pl_Float x, pl_Float y, pl_Float z);
pl_Float Pitch, Pan, Roll; /* Camera angle in degrees in worldspace */
pl_Float Fov; /* FOV in degrees valid range is 1-179 */
pl_Float AspectRatio; /* Aspect ratio (usually 1.0) */
pl_Float ClipBack WDL_FIXALIGN; /* Far clipping ( < 0.0 is none) */
pl_Float X, Y, Z; /* Camera position in worldspace */
pl_Float CamMatrix[16]; /* should be rotation-only. translation will mess with the normals */
pl_sChar Sort; /* Sort polygons, -1 f-t-b, 1 b-t-f, 0 no */
pl_sInt CenterX, CenterY; /* Offset center of screen from actual center by this much... */
pl_Bool WantZBuffer;
pl_Bool GenMatrix; /* if set, generates CamMatrix from Pan/Pitch/Roll in Begin() */
void Begin(LICE_IBitmap *fb, bool want_zbclear=true, pl_ZBuffer zbclear=0.0);
void RenderLight(pl_Light *light);
void RenderObject(pl_Obj *obj, const pl_Float *bmatrix=NULL, const pl_Float *bnmatrix=NULL);
void SortToCurrent(); // sorts all faces added since Begin() or last SortToCurrent() call. useful for if you use zbuffering with transparent objects (draw them last)
// returns true if onscreen x/y/z are world coordinates
bool ProjectCoordinate(pl_Float x, pl_Float y, pl_Float z, pl_Float *screen_x, pl_Float *screen_y, pl_Float *dist); // outputs can be NULL if not needed
LICE_IBitmap *GetFrameBuffer() { return m_fBuffer.m_buf ? &m_fBuffer : NULL; }
WDL_TypedBuf<pl_ZBuffer> zBuffer; /* Z Buffer (validate size before using)*/
void End();
int RenderTrisIn;
int RenderTrisCulled;
int RenderTrisOut;
double RenderPixelsOut WDL_FIXALIGN;
void PutFace(pl_Face *TriFace);
protected:
LICE_WrapperBitmap m_fBuffer;
pl_uInt m_lastFBWidth, m_lastFBHeight; // unscaled sizes when compared to m_fBuffer
pl_uInt m_lastFBScaling;
pl_sInt m_lastCX, m_lastCY; // calculated as w/2+CenterX/2 etc
// internal use
void ClipRenderFace(pl_Face *face, pl_Obj *obj);
int ClipNeeded(pl_Face *face, pl_Obj *obj); // 0=no draw, 1=drawing (possibly splitting) necessary
void RecalcFrustum(int fbw, int fbh);
double CalcFOVFactor(double fbw) const
{
return fbw/tan(plMin(plMax(Fov,1.0),179.0)*(PL_PI/360.0));
}
#define PL_NUM_CLIP_PLANES 5
struct _clipInfo
{
pl_Vertex newVertices[8];
pl_Float ShadeInfos[8][3];
pl_Float MappingU[PLUSH_MAX_MAPCOORDS][8];
pl_Float MappingV[PLUSH_MAX_MAPCOORDS][8];
};
_clipInfo m_cl[2] WDL_FIXALIGN;
pl_Float m_clipPlanes[PL_NUM_CLIP_PLANES][4];
pl_Float m_fovfactor, m_adj_asp; // recalculated
/* Returns: 0 if nothing gets in, 1 or 2 if pout1 & pout2 get in */
pl_uInt _ClipToPlane(pl_uInt numVerts, pl_Float *plane);
struct _faceInfo {
pl_Float zd;
pl_Face *face;
pl_Obj *obj;
} WDL_FIXALIGN;
struct _lightInfo {
pl_Float l[3];
pl_Light *light;
} WDL_FIXALIGN;
static int sortRevFunc(const void *a, const void *b);
static int sortFwdFunc(const void *a, const void *b);
int _numfaces,_numfaces_sorted;
WDL_TypedBuf<_faceInfo> _faces;
int _numlights;
WDL_TypedBuf<_lightInfo> _lights;
void _RenderObj(pl_Obj *, pl_Float *, pl_Float *);
WDL_HeapBuf _sort_tmpspace;
};
/******************************************************************************
** Object Primitives Code (pl_make.cpp)
******************************************************************************/
/*
plMakePlane() makes a plane centered at the origin facing up the y axis.
Parameters:
w: width of the plane (along the x axis)
d: depth of the plane (along the z axis)
res: resolution of plane, i.e. subdivisions
m: material to use
Returns:
pointer to object created.
*/
pl_Obj *plMakePlane(pl_Float w, pl_Float d, pl_uInt res, pl_Mat *m);
/*
plMakeBox() makes a box centered at the origin
Parameters:
w: width of the box (x axis)
d: depth of the box (z axis)
h: height of the box (y axis)
Returns:
pointer to object created.
*/
pl_Obj *plMakeBox(pl_Float w, pl_Float d, pl_Float h, pl_Mat *m);
/*
plMakeDisc() makes a disc centered at the origin
Parameters:
r: radius of the disc (x-z axis)
divr: division of of disc (around the circle) (>=3)
m: material to use
Returns:
pointer to object created.
*/
pl_Obj *plMakeDisc(pl_Float r, pl_uInt divr, pl_Mat *m);
/*
plMakeCone() makes a cone centered at the origin
Parameters:
r: radius of the cone (x-z axis)
h: height of the cone (y axis)
div: division of cone (>=3)
cap: close the big end?
m: material to use
Returns:
pointer to object created.
*/
pl_Obj *plMakeCone(pl_Float r, pl_Float h, pl_uInt div, pl_Bool cap, pl_Mat *m);
/*
plMakeCylinder() makes a cylinder centered at the origin
Parameters:
r: radius of the cylinder (x-z axis)
h: height of the cylinder (y axis)
divr: division of of cylinder (around the circle) (>=3)
captop: close the top
capbottom: close the bottom
m: material to use
Returns:
pointer to object created.
*/
pl_Obj *plMakeCylinder(pl_Float r, pl_Float h, pl_uInt divr, pl_Bool captop,
pl_Bool capbottom, pl_Mat *m);
/*
plMakeSphere() makes a sphere centered at the origin.
Parameters:
r: radius of the sphere
divr: division of the sphere (around the y axis) (>=3)
divh: division of the sphere (around the x,z axis) (>=3)
m: material to use
Returns:
pointer to object created.
*/
pl_Obj *plMakeSphere(pl_Float r, pl_uInt divr, pl_uInt divh, pl_Mat *m);
/*
plMakeTorus() makes a torus centered at the origin
Parameters:
r1: inner radius of the torus
r2: outer radius of the torus
divrot: division of the torus (around the y axis) (>=3)
divrad: division of the radius of the torus (x>=3)
m: material to use
Returns:
pointer to object created.
*/
pl_Obj *plMakeTorus(pl_Float r1, pl_Float r2, pl_uInt divrot,
pl_uInt divrad, pl_Mat *m);
/******************************************************************************
** File Readers (pl_read_*.cpp)
******************************************************************************/
/*
plRead3DSObj() reads a 3DS object
Parameters:
fn: filename of object to read
m: material to assign it
Returns:
pointer to object
Notes:
This reader organizes multiple objects like so:
1) the first object is returned
2) the second object is the first's first child
3) the third object is the second's first child
4) etc
*/
pl_Obj *plRead3DSObj(void *ptr, int size, pl_Mat *m);
pl_Obj *plRead3DSObjFromFile(char *fn, pl_Mat *m);
pl_Obj *plRead3DSObjFromResource(HINSTANCE hInst, int resid, pl_Mat *m);
/*
plReadCOBObj() reads an ascii .COB object
Parameters:
fn: filename of object to read
mat: material to assign it
Returns:
pointer to object
Notes:
This is Caligari's ASCII object format.
This reader doesn't handle multiple objects. It just reads the first one.
Polygons with lots of sides are not always tesselated correctly. Just
use the "Tesselate" button from within truespace to improve the results.
*/
pl_Obj *plReadCOBObj(char *fn, pl_Mat *mat);
/*
plReadJAWObj() reads a .JAW object.
Parameters:
fn: filename of object to read
m: material to assign it
Returns:
pointer to object
Notes:
For information on the .JAW format, please see the jaw3D homepage,
http://www.tc.umn.edu/nlhome/g346/kari0022/jaw3d/
*/
pl_Obj *plReadJAWObj(char *fn, pl_Mat *m);
/******************************************************************************
** Math Code (pl_math.cpp)
******************************************************************************/
/*
plMatrixRotate() generates a rotation matrix
Parameters:
matrix: an array of 16 pl_Floats that is a 4x4 matrix
m: the axis to rotate around, 1=X, 2=Y, 3=Z.
Deg: the angle in degrees to rotate
Returns:
nothing
*/
void plMatrixRotate(pl_Float matrix[], pl_uChar m, pl_Float Deg);
/*
plMatrixTranslate() generates a translation matrix
Parameters:
m: the matrix (see plMatrixRotate for more info)
x,y,z: the translation coordinates
Returns:
nothing
*/
void plMatrixTranslate(pl_Float m[], pl_Float x, pl_Float y, pl_Float z);
/*
plMatrixMultiply() multiplies two matrices
Parameters:
dest: destination matrix will be multipled by src
src: source matrix
Returns:
nothing
Notes:
this is the same as dest = dest*src (since the order *does* matter);
*/
void plMatrixMultiply(pl_Float *dest, const pl_Float src[]);
/*
plMatrixApply() applies a matrix.
Parameters:
m: matrix to apply
x,y,z: input coordinate
outx,outy,outz: pointers to output coords.
Returns:
nothing
Notes:
applies the matrix to the 3d point to produce the transformed 3d point
*/
void plMatrixApply(pl_Float *m, pl_Float x, pl_Float y, pl_Float z,
pl_Float *outx, pl_Float *outy, pl_Float *outz);
/*
plNormalizeVector() makes a vector a unit vector
Parameters:
x,y,z: pointers to the vector
Returns:
nothing
*/
void plNormalizeVector(pl_Float *x, pl_Float *y, pl_Float *z);
/*
plDotProduct() returns the dot product of two vectors
Parameters:
x1,y1,z1: the first vector
x2,y2,z2: the second vector
Returns:
the dot product of the two vectors
*/
pl_Float plDotProduct(pl_Float x1, pl_Float y1, pl_Float z1,
pl_Float x2, pl_Float y2, pl_Float z2);
#endif /* !_PLUSH_H_ */