RENDER.C 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /******************************************************************************
  2. Plush Version 1.2
  3. render.c
  4. Rendering code: this includes transformation, lighting, etc
  5. Copyright (c) 1996-2000, Justin Frankel
  6. ******************************************************************************/
  7. #include "plush.h"
  8. typedef struct {
  9. pl_Float zd;
  10. pl_Face *face;
  11. } _faceInfo;
  12. typedef struct {
  13. pl_Light *light;
  14. pl_Float l[3];
  15. } _lightInfo;
  16. #define MACRO_plMatrixApply(m,x,y,z,outx,outy,outz) \
  17. ( outx ) = ( x )*( m )[0] + ( y )*( m )[1] + ( z )*( m )[2] + ( m )[3];\
  18. ( outy ) = ( x )*( m )[4] + ( y )*( m )[5] + ( z )*( m )[6] + ( m )[7];\
  19. ( outz ) = ( x )*( m )[8] + ( y )*( m )[9] + ( z )*( m )[10] + ( m )[11]
  20. #define MACRO_plDotProduct(x1,y1,z1,x2,y2,z2) \
  21. ((( x1 )*( x2 ))+(( y1 )*( y2 ))+(( z1 )*( z2 )))
  22. #define MACRO_plNormalizeVector(x,y,z) { \
  23. register double length; \
  24. length = ( x )*( x )+( y )*( y )+( z )*( z ); \
  25. if (length > 0.0000000001) { \
  26. pl_Float l = (pl_Float) sqrt(length); \
  27. ( x ) /= l; \
  28. ( y ) /= l; \
  29. ( z ) /= l; \
  30. } \
  31. }
  32. pl_uInt32 plRender_TriStats[4];
  33. static pl_uInt32 _numfaces;
  34. static _faceInfo _faces[PL_MAX_TRIANGLES];
  35. static pl_Float _cMatrix[16];
  36. static pl_uInt32 _numlights;
  37. static _lightInfo _lights[PL_MAX_LIGHTS];
  38. static pl_Cam *_cam;
  39. static void _RenderObj(pl_Obj *, pl_Float *, pl_Float *);
  40. static void _sift_down(int L, int U, int dir);
  41. static void _hsort(_faceInfo *base, int nel, int dir);
  42. void plRenderBegin(pl_Cam *Camera) {
  43. pl_Float tempMatrix[16];
  44. memset(plRender_TriStats,0,sizeof(plRender_TriStats));
  45. _cam = Camera;
  46. _numlights = 0;
  47. _numfaces = 0;
  48. plMatrixRotate(_cMatrix,2,-Camera->Pan);
  49. plMatrixRotate(tempMatrix,1,-Camera->Pitch);
  50. plMatrixMultiply(_cMatrix,tempMatrix);
  51. plMatrixRotate(tempMatrix,3,-Camera->Roll);
  52. plMatrixMultiply(_cMatrix,tempMatrix);
  53. plClipSetFrustum(_cam);
  54. }
  55. void plRenderLight(pl_Light *light) {
  56. pl_Float *pl, xp, yp, zp;
  57. if (light->Type == PL_LIGHT_NONE || _numlights >= PL_MAX_LIGHTS) return;
  58. pl = _lights[_numlights].l;
  59. if (light->Type == PL_LIGHT_VECTOR) {
  60. xp = light->Xp;
  61. yp = light->Yp;
  62. zp = light->Zp;
  63. MACRO_plMatrixApply(_cMatrix,xp,yp,zp,pl[0],pl[1],pl[2]);
  64. } else if (light->Type & PL_LIGHT_POINT) {
  65. xp = light->Xp-_cam->X;
  66. yp = light->Yp-_cam->Y;
  67. zp = light->Zp-_cam->Z;
  68. MACRO_plMatrixApply(_cMatrix,xp,yp,zp,pl[0],pl[1],pl[2]);
  69. }
  70. _lights[_numlights++].light = light;
  71. }
  72. static void _RenderObj(pl_Obj *obj, pl_Float *bmatrix, pl_Float *bnmatrix) {
  73. pl_uInt32 i, x, facepos;
  74. pl_Float nx = 0.0, ny = 0.0, nz = 0.0;
  75. double tmp, tmp2;
  76. pl_Float oMatrix[16], nMatrix[16], tempMatrix[16];
  77. pl_Vertex *vertex;
  78. pl_Face *face;
  79. pl_Light *light;
  80. if (obj->GenMatrix) {
  81. plMatrixRotate(nMatrix,1,obj->Xa);
  82. plMatrixRotate(tempMatrix,2,obj->Ya);
  83. plMatrixMultiply(nMatrix,tempMatrix);
  84. plMatrixRotate(tempMatrix,3,obj->Za);
  85. plMatrixMultiply(nMatrix,tempMatrix);
  86. memcpy(oMatrix,nMatrix,sizeof(pl_Float)*16);
  87. } else memcpy(nMatrix,obj->RotMatrix,sizeof(pl_Float)*16);
  88. if (bnmatrix) plMatrixMultiply(nMatrix,bnmatrix);
  89. if (obj->GenMatrix) {
  90. plMatrixTranslate(tempMatrix, obj->Xp, obj->Yp, obj->Zp);
  91. plMatrixMultiply(oMatrix,tempMatrix);
  92. } else memcpy(oMatrix,obj->Matrix,sizeof(pl_Float)*16);
  93. if (bmatrix) plMatrixMultiply(oMatrix,bmatrix);
  94. for (i = 0; i < PL_MAX_CHILDREN; i ++)
  95. if (obj->Children[i]) _RenderObj(obj->Children[i],oMatrix,nMatrix);
  96. if (!obj->NumFaces || !obj->NumVertices) return;
  97. plMatrixTranslate(tempMatrix, -_cam->X, -_cam->Y, -_cam->Z);
  98. plMatrixMultiply(oMatrix,tempMatrix);
  99. plMatrixMultiply(oMatrix,_cMatrix);
  100. plMatrixMultiply(nMatrix,_cMatrix);
  101. x = obj->NumVertices;
  102. vertex = obj->Vertices;
  103. do {
  104. MACRO_plMatrixApply(oMatrix,vertex->x,vertex->y,vertex->z,
  105. vertex->xformedx, vertex->xformedy, vertex->xformedz);
  106. MACRO_plMatrixApply(nMatrix,vertex->nx,vertex->ny,vertex->nz,
  107. vertex->xformednx,vertex->xformedny,vertex->xformednz);
  108. vertex++;
  109. } while (--x);
  110. face = obj->Faces;
  111. facepos = _numfaces;
  112. if (_numfaces + obj->NumFaces >= PL_MAX_TRIANGLES) // exceeded maximum face coutn
  113. {
  114. return;
  115. }
  116. plRender_TriStats[0] += obj->NumFaces;
  117. _numfaces += obj->NumFaces;
  118. x = obj->NumFaces;
  119. do {
  120. if (obj->BackfaceCull || face->Material->_st & PL_SHADE_FLAT)
  121. {
  122. MACRO_plMatrixApply(nMatrix,face->nx,face->ny,face->nz,nx,ny,nz);
  123. }
  124. if (!obj->BackfaceCull || (MACRO_plDotProduct(nx,ny,nz,
  125. face->Vertices[0]->xformedx, face->Vertices[0]->xformedy,
  126. face->Vertices[0]->xformedz) < 0.0000001)) {
  127. if (plClipNeeded(face)) {
  128. if (face->Material->_st & (PL_SHADE_FLAT|PL_SHADE_FLAT_DISTANCE)) {
  129. tmp = face->sLighting;
  130. if (face->Material->_st & PL_SHADE_FLAT) {
  131. for (i = 0; i < _numlights; i ++) {
  132. tmp2 = 0.0;
  133. light = _lights[i].light;
  134. if (light->Type & PL_LIGHT_POINT_ANGLE) {
  135. double nx2 = _lights[i].l[0] - face->Vertices[0]->xformedx;
  136. double ny2 = _lights[i].l[1] - face->Vertices[0]->xformedy;
  137. double nz2 = _lights[i].l[2] - face->Vertices[0]->xformedz;
  138. MACRO_plNormalizeVector(nx2,ny2,nz2);
  139. tmp2 = MACRO_plDotProduct(nx,ny,nz,nx2,ny2,nz2)*light->Intensity;
  140. }
  141. if (light->Type & PL_LIGHT_POINT_DISTANCE) {
  142. double nx2 = _lights[i].l[0] - face->Vertices[0]->xformedx;
  143. double ny2 = _lights[i].l[1] - face->Vertices[0]->xformedy;
  144. double nz2 = _lights[i].l[2] - face->Vertices[0]->xformedz;
  145. if (light->Type & PL_LIGHT_POINT_ANGLE) {
  146. nx2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/
  147. light->HalfDistSquared));
  148. tmp2 *= plMax(0,plMin(1.0,nx2))*light->Intensity;
  149. } else {
  150. tmp2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/
  151. light->HalfDistSquared));
  152. tmp2 = plMax(0,plMin(1.0,tmp2))*light->Intensity;
  153. }
  154. }
  155. if (light->Type == PL_LIGHT_VECTOR)
  156. tmp2 = MACRO_plDotProduct(nx,ny,nz,_lights[i].l[0],_lights[i].l[1],_lights[i].l[2])
  157. * light->Intensity;
  158. if (tmp2 > 0.0) tmp += tmp2;
  159. else if (obj->BackfaceIllumination) tmp -= tmp2;
  160. } /* End of light loop */
  161. } /* End of flat shading if */
  162. if (face->Material->_st & PL_SHADE_FLAT_DISTANCE)
  163. tmp += 1.0-(face->Vertices[0]->xformedz+face->Vertices[1]->xformedz+
  164. face->Vertices[2]->xformedz) /
  165. (face->Material->FadeDist*3.0);
  166. face->fShade = (pl_Float) tmp;
  167. } else face->fShade = 0.0; /* End of flatmask lighting if */
  168. if (face->Material->_ft & PL_FILL_ENVIRONMENT) {
  169. face->eMappingU[0] = 32768 + (pl_sInt32) (face->Vertices[0]->xformednx*32768.0);
  170. face->eMappingV[0] = 32768 - (pl_sInt32) (face->Vertices[0]->xformedny*32768.0);
  171. face->eMappingU[1] = 32768 + (pl_sInt32) (face->Vertices[1]->xformednx*32768.0);
  172. face->eMappingV[1] = 32768 - (pl_sInt32) (face->Vertices[1]->xformedny*32768.0);
  173. face->eMappingU[2] = 32768 + (pl_sInt32) (face->Vertices[2]->xformednx*32768.0);
  174. face->eMappingV[2] = 32768 - (pl_sInt32) (face->Vertices[2]->xformedny*32768.0);
  175. }
  176. if (face->Material->_st &(PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE)) {
  177. register pl_uChar a;
  178. for (a = 0; a < 3; a ++) {
  179. tmp = face->vsLighting[a];
  180. if (face->Material->_st & PL_SHADE_GOURAUD) {
  181. for (i = 0; i < _numlights ; i++) {
  182. tmp2 = 0.0;
  183. light = _lights[i].light;
  184. if (light->Type & PL_LIGHT_POINT_ANGLE) {
  185. nx = _lights[i].l[0] - face->Vertices[a]->xformedx;
  186. ny = _lights[i].l[1] - face->Vertices[a]->xformedy;
  187. nz = _lights[i].l[2] - face->Vertices[a]->xformedz;
  188. MACRO_plNormalizeVector(nx,ny,nz);
  189. tmp2 = MACRO_plDotProduct(face->Vertices[a]->xformednx,
  190. face->Vertices[a]->xformedny,
  191. face->Vertices[a]->xformednz,
  192. nx,ny,nz) * light->Intensity;
  193. }
  194. if (light->Type & PL_LIGHT_POINT_DISTANCE) {
  195. double nx2 = _lights[i].l[0] - face->Vertices[a]->xformedx;
  196. double ny2 = _lights[i].l[1] - face->Vertices[a]->xformedy;
  197. double nz2 = _lights[i].l[2] - face->Vertices[a]->xformedz;
  198. if (light->Type & PL_LIGHT_POINT_ANGLE) {
  199. double t= (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared));
  200. tmp2 *= plMax(0,plMin(1.0,t))*light->Intensity;
  201. } else {
  202. tmp2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared));
  203. tmp2 = plMax(0,plMin(1.0,tmp2))*light->Intensity;
  204. }
  205. }
  206. if (light->Type == PL_LIGHT_VECTOR)
  207. tmp2 = MACRO_plDotProduct(face->Vertices[a]->xformednx,
  208. face->Vertices[a]->xformedny,
  209. face->Vertices[a]->xformednz,
  210. _lights[i].l[0],_lights[i].l[1],_lights[i].l[2])
  211. * light->Intensity;
  212. if (tmp2 > 0.0) tmp += tmp2;
  213. else if (obj->BackfaceIllumination) tmp -= tmp2;
  214. } /* End of light loop */
  215. } /* End of gouraud shading if */
  216. if (face->Material->_st & PL_SHADE_GOURAUD_DISTANCE)
  217. tmp += 1.0-face->Vertices[a]->xformedz/face->Material->FadeDist;
  218. face->Shades[a] = (pl_Float) tmp;
  219. } /* End of vertex loop for */
  220. } /* End of gouraud shading mask if */
  221. _faces[facepos].zd = face->Vertices[0]->xformedz+
  222. face->Vertices[1]->xformedz+face->Vertices[2]->xformedz;
  223. _faces[facepos++].face = face;
  224. plRender_TriStats[1] ++;
  225. } /* Is it in our area Check */
  226. } /* Backface Check */
  227. _numfaces = facepos;
  228. face++;
  229. } while (--x); /* Face loop */
  230. }
  231. void plRenderObj(pl_Obj *obj) {
  232. _RenderObj(obj,0,0);
  233. }
  234. void plRenderEnd() {
  235. _faceInfo *f;
  236. if (_cam->Sort > 0) _hsort(_faces,_numfaces,0);
  237. else if (_cam->Sort < 0) _hsort(_faces,_numfaces,1);
  238. f = _faces;
  239. while (_numfaces--) {
  240. if (f->face->Material && f->face->Material->_PutFace)
  241. {
  242. plClipRenderFace(f->face);
  243. }
  244. f++;
  245. }
  246. _numfaces=0;
  247. _numlights = 0;
  248. }
  249. static _faceInfo *Base, tmp;
  250. static void _hsort(_faceInfo *base, int nel, int dir) {
  251. static int i;
  252. Base=base-1;
  253. for (i=nel/2; i>0; i--) _sift_down(i,nel,dir);
  254. for (i=nel; i>1; ) {
  255. tmp = base[0]; base[0] = Base[i]; Base[i] = tmp;
  256. _sift_down(1,i-=1,dir);
  257. }
  258. }
  259. #define Comp(x,y) (( x ).zd < ( y ).zd ? 1 : 0)
  260. static void _sift_down(int L, int U, int dir) {
  261. static int c;
  262. while (1) {
  263. c=L+L;
  264. if (c>U) break;
  265. if ( (c < U) && dir^Comp(Base[c+1],Base[c])) c++;
  266. if (dir^Comp(Base[L],Base[c])) return;
  267. tmp = Base[L]; Base[L] = Base[c]; Base[c] = tmp;
  268. L=c;
  269. }
  270. }
  271. #undef Comp