00001
00002 #include "revolt.h"
00003 #include "geom.h"
00004 #include "newcoll.h"
00005 #include "shadow.h"
00006 #include "text.h"
00007 #include "dx.h"
00008 #include "geom.h"
00009 #include "texture.h"
00010 #include "camera.h"
00011 #include "draw.h"
00012
00013 static unsigned short ShadowVertNum, ShadowVertFree;
00014 static unsigned short ShadowVertList[2][8];
00015 static SHADOW_VERT ShadowVert[32];
00016 static VERTEX_TEX1 ShadowDrawVert[8];
00017
00019
00021
00022 void DrawShadow(VEC *p0, VEC *p1, VEC *p2, VEC *p3, REAL tu, REAL tv, REAL twidth, REAL theight, long rgb, REAL yoff, REAL maxy, long semi, long tpage, BOUNDING_BOX *box)
00023 {
00024 short i, j, k, newcount, vcount, togg;
00025 float dist0, dist1, dist2, dist3;
00026 float ldist0, ldist1, ldist2, ldist3;
00027 float xmin, xmax, ymin, ymax, zmin, zmax;
00028 NEWCOLLPOLY *p;
00029 VEC lp0, lp1, lp2, lp3, pos;
00030 SHADOW_VERT *vert0, *vert1;
00031 PLANE *plane;
00032 COLLGRID *header;
00033 VERTEX_TEX1 *vert;
00034 SHADOW_VERT *svert;
00035
00036
00037
00038 xmin = xmax = p0->v[X];
00039 ymin = p0->v[Y];
00040 zmin = zmax = p0->v[Z];
00041
00042 if (p1->v[X] < xmin) xmin = p1->v[X];
00043 if (p1->v[X] > xmax) xmax = p1->v[X];
00044 if (p1->v[Y] < ymin) ymin = p1->v[Y];
00045 if (p1->v[Z] < zmin) zmin = p1->v[Z];
00046 if (p1->v[Z] > zmax) zmax = p1->v[Z];
00047
00048 if (p2->v[X] < xmin) xmin = p2->v[X];
00049 if (p2->v[X] > xmax) xmax = p2->v[X];
00050 if (p2->v[Y] < ymin) ymin = p2->v[Y];
00051 if (p2->v[Z] < zmin) zmin = p2->v[Z];
00052 if (p2->v[Z] > zmax) zmax = p2->v[Z];
00053
00054 if (p3->v[X] < xmin) xmin = p3->v[X];
00055 if (p3->v[X] > xmax) xmax = p3->v[X];
00056 if (p3->v[Y] < ymin) ymin = p3->v[Y];
00057 if (p3->v[Z] < zmin) zmin = p3->v[Z];
00058 if (p3->v[Z] > zmax) zmax = p3->v[Z];
00059
00060 if (maxy)
00061 ymax = ymin + maxy;
00062 else
00063 ymax = 1000000.0f;
00064
00065
00066
00067 SetVector(&lp0, p0->v[X], p0->v[Y] - 256, p0->v[Z]);
00068 SetVector(&lp1, p1->v[X], p1->v[Y] - 256, p1->v[Z]);
00069 SetVector(&lp2, p2->v[X], p2->v[Y] - 256, p2->v[Z]);
00070 SetVector(&lp3, p3->v[X], p3->v[Y] - 256, p3->v[Z]);
00071
00072
00073
00074 if (box)
00075 {
00076 box->Xmin = box->Ymin = box->Zmin = 1000000.0f;
00077 box->Xmax = box->Ymax = box->Zmax = -1000000.0f;
00078 }
00079
00080
00081
00082 SetVector(&pos, (p0->v[X] + p2->v[X]) / 2, (p0->v[Y] + p2->v[Y]) / 2, (p0->v[Z] + p2->v[Z]) / 2);
00083 header = PosToCollGrid(&pos);
00084 if (header == NULL) return;
00085
00086 for (i = 0 ; i < header->NCollPolys ; i++)
00087 {
00088
00089
00090
00091 p = header->CollPolyPtr[i];
00092
00093
00094
00095 if (p->Plane.v[B] > -0.1f) continue;
00096 if (xmin > p->BBox.XMax || xmax < p->BBox.XMin || zmin > p->BBox.ZMax || zmax < p->BBox.ZMin || ymin > p->BBox.YMax || ymax < p->BBox.YMin) continue;
00097
00098
00099
00100 dist0 = -PlaneDist(&p->Plane, p0);
00101 dist1 = -PlaneDist(&p->Plane, p1);
00102 dist2 = -PlaneDist(&p->Plane, p2);
00103 dist3 = -PlaneDist(&p->Plane, p3);
00104
00105
00106
00107 if (dist0 >= 0 && dist1 >= 0 && dist2 >= 0 && dist3 >= 0) continue;
00108
00109
00110
00111 ldist0 = -PlaneDist(&p->Plane, &lp0);
00112 ldist1 = -PlaneDist(&p->Plane, &lp1);
00113 ldist2 = -PlaneDist(&p->Plane, &lp2);
00114 ldist3 = -PlaneDist(&p->Plane, &lp3);
00115
00116 FindIntersection(&lp0, ldist0, p0, dist0, &ShadowVert[0].Pos);
00117 FindIntersection(&lp1, ldist1, p1, dist1, &ShadowVert[1].Pos);
00118 FindIntersection(&lp2, ldist2, p2, dist2, &ShadowVert[2].Pos);
00119 FindIntersection(&lp3, ldist3, p3, dist3, &ShadowVert[3].Pos);
00120
00121
00122
00123 ShadowVert[0].tu = tu;
00124 ShadowVert[0].tv = tv;
00125 ShadowVert[1].tu = tu + twidth;
00126 ShadowVert[1].tv = tv;
00127 ShadowVert[2].tu = tu + twidth;
00128 ShadowVert[2].tv = tv + theight;
00129 ShadowVert[3].tu = tu;
00130 ShadowVert[3].tv = tv + theight;
00131
00132
00133
00134 ShadowVertNum = 4;
00135 ShadowVertFree = 4;
00136
00137 ShadowVertList[0][0] = 0;
00138 ShadowVertList[0][1] = 1;
00139 ShadowVertList[0][2] = 2;
00140 ShadowVertList[0][3] = 3;
00141
00142
00143
00144 vcount = 3 + (p->Type & QUAD);
00145 togg = TRUE;
00146
00147 for (j = 0 ; j < vcount ; j++)
00148 {
00149 plane = &p->EdgePlane[j];
00150
00151
00152
00153 for (k = newcount = 0 ; k < ShadowVertNum ; k++)
00154 {
00155 vert0 = ShadowVert + ShadowVertList[!togg][k];
00156 vert1 = ShadowVert + ShadowVertList[!togg][(k + 1) % ShadowVertNum];
00157
00158 dist0 = PlaneDist(plane, &vert0->Pos);
00159 if (dist0 <= 0)
00160 {
00161 ShadowVertList[togg][newcount++] = ShadowVertList[!togg][k];
00162
00163 dist1 = PlaneDist(plane, &vert1->Pos);
00164 if (dist1 > 0)
00165 {
00166 ClipShadowEdge(vert1, vert0, dist1 / (dist1 - dist0), ShadowVert + ShadowVertFree);
00167 ShadowVertList[togg][newcount++] = ShadowVertFree++;
00168 }
00169 }
00170 else
00171 {
00172 dist1 = PlaneDist(plane, &vert1->Pos);
00173 if (dist1 <= 0)
00174 {
00175 ClipShadowEdge(vert0, vert1, dist0 / (dist0 - dist1), ShadowVert + ShadowVertFree);
00176 ShadowVertList[togg][newcount++] = ShadowVertFree++;
00177 }
00178 }
00179 }
00180 ShadowVertNum = newcount;
00181 togg = !togg;
00182 }
00183
00184
00185
00186 for (j = 0 ; j < ShadowVertNum ; j++)
00187 {
00188 svert = &ShadowVert[ShadowVertList[!togg][j]];
00189
00190
00191
00192 if (box)
00193 {
00194 if (svert->Pos.v[X] < box->Xmin) box->Xmin = svert->Pos.v[X];
00195 if (svert->Pos.v[X] > box->Xmax) box->Xmax = svert->Pos.v[X];
00196 if (svert->Pos.v[Y] < box->Ymin) box->Ymin = svert->Pos.v[Y];
00197 if (svert->Pos.v[Y] > box->Ymax) box->Ymax = svert->Pos.v[Y];
00198 if (svert->Pos.v[Z] < box->Zmin) box->Zmin = svert->Pos.v[Z];
00199 if (svert->Pos.v[Z] > box->Zmax) box->Zmax = svert->Pos.v[Z];
00200 }
00201
00202
00203
00204 svert->Pos.v[Y] += yoff;
00205
00206 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &svert->Pos, &ShadowDrawVert[j].sx);
00207 ShadowDrawVert[j].tu = svert->tu;
00208 ShadowDrawVert[j].tv = svert->tv;
00209 ShadowDrawVert[j].color = rgb;
00210
00211 }
00212
00213
00214
00215 if (semi == -1)
00216 {
00217 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, ShadowDrawVert, ShadowVertNum, D3DDP_DONOTUPDATEEXTENTS);
00218 }
00219 else
00220 {
00221 for (j = 0 ; j < ShadowVertNum - 2 ; j++)
00222 {
00223 if (!SEMI_POLY_FREE()) continue;
00224 SEMI_POLY_SETUP_ZBIAS(vert, FALSE, 3, tpage, TRUE, semi, -256.0f);
00225
00226 *(MEM32*)&vert[0] = *(MEM32*)&ShadowDrawVert[0];
00227 *(MEM32*)&vert[1] = *(MEM32*)&ShadowDrawVert[j + 1];
00228 *(MEM32*)&vert[2] = *(MEM32*)&ShadowDrawVert[j + 2];
00229 }
00230 }
00231 }
00232 }
00233
00235
00237
00238 void ClipShadowEdge(SHADOW_VERT *sv0, SHADOW_VERT *sv1, float mul, SHADOW_VERT *svout)
00239 {
00240 svout->Pos.v[X] = sv0->Pos.v[X] + (sv1->Pos.v[X] - sv0->Pos.v[X]) * mul;
00241 svout->Pos.v[Y] = sv0->Pos.v[Y] + (sv1->Pos.v[Y] - sv0->Pos.v[Y]) * mul;
00242 svout->Pos.v[Z] = sv0->Pos.v[Z] + (sv1->Pos.v[Z] - sv0->Pos.v[Z]) * mul;
00243
00244 svout->tu = sv0->tu + (sv1->tu - sv0->tu) * mul;
00245 svout->tv = sv0->tv + (sv1->tv - sv0->tv) * mul;
00246 }