1 /*
2 * Copyright 2011-2012 Arx Libertatis Team (see the AUTHORS file)
3 *
4 * This file is part of Arx Libertatis.
5 *
6 * Arx Libertatis is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Arx Libertatis is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Arx Libertatis. If not, see <http://www.gnu.org/licenses/>.
18 */
19 /* Based on:
20 ===========================================================================
21 ARX FATALIS GPL Source Code
22 Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
23
24 This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
25
26 Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
27 License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
28
29 Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
30 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
33 <http://www.gnu.org/licenses/>.
34
35 In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
36 additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
37 Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
38
39 If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
40 ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
41 ===========================================================================
42 */
43
44 #include "graphics/Draw.h"
45
46 #include "core/Application.h"
47 #include "core/GameTime.h"
48
49 #include "graphics/VertexBuffer.h"
50 #include "graphics/Math.h"
51 #include "graphics/data/TextureContainer.h"
52 #include "graphics/data/Mesh.h"
53
54 using std::min;
55 using std::max;
56
57 TextureContainer * EERIE_DRAW_sphere_particle=NULL;
58
59 long ZMAPMODE=1;
60 TextureContainer * Zmap;
61 Vec3f SPRmins;
62 Vec3f SPRmaxs;
63
64 extern TextureContainer * enviro;
65
CopyVertices(EERIEPOLY * ep,long to,long from)66 void CopyVertices(EERIEPOLY * ep,long to, long from) {
67 ep->v[to] = ep->v[from];
68 ep->tv[to] = ep->tv[from];
69 ep->nrml[to] = ep->nrml[from];
70 }
71
NearlyEqual(float a,float b)72 bool NearlyEqual(float a,float b)
73 {
74 if (EEfabs(a-b)<0.01f) return true;
75
76 if (EEfabs(b-a)<0.01f) return true;
77
78 return false;
79 }
80
Quadable(EERIEPOLY * ep,EERIEPOLY * ep2,float tolerance)81 bool Quadable(EERIEPOLY * ep, EERIEPOLY * ep2, float tolerance)
82 {
83
84 long count=0;
85 long common=-1;
86 long common2=-1;
87
88
89 long ep_notcommon=-1;
90 long ep2_notcommon=-1;
91
92 if (ep2->type & POLY_QUAD)
93 {
94 return false;
95 }
96
97 if (ep->tex != ep2->tex) return false;
98
99 long typ1=ep->type&(~POLY_QUAD);
100 long typ2=ep2->type&(~POLY_QUAD);
101
102 if (typ1!=typ2) return false;
103
104 if ((ep->type & POLY_TRANS) && (ep->transval!=ep2->transval)) return false;
105
106 CalcFaceNormal(ep,ep->v);
107
108 if (fabs(dot(ep->norm, ep2->norm)) < 1.f - tolerance) return false;
109
110 for (long i=0;i<3;i++)
111 {
112 common=-1;
113 common2=-1;
114
115 for (long j=0;j<3;j++)
116 {
117 if ( ( NearlyEqual(ep->v[i].p.x,ep2->v[j].p.x) )
118 && ( NearlyEqual(ep->v[i].p.y,ep2->v[j].p.y) )
119 && ( NearlyEqual(ep->v[i].p.z,ep2->v[j].p.z) )
120 && ( NearlyEqual(ep->v[i].uv.x,ep2->v[j].uv.x) )
121 && ( NearlyEqual(ep->v[i].uv.y,ep2->v[j].uv.y) )
122 )
123 {
124 count++;
125 common=j;
126 }
127
128 if ( ( NearlyEqual(ep->v[j].p.x,ep2->v[i].p.x) )
129 && ( NearlyEqual(ep->v[j].p.y,ep2->v[i].p.y) )
130 && ( NearlyEqual(ep->v[j].p.z,ep2->v[i].p.z) )
131 && ( NearlyEqual(ep->v[j].uv.x,ep2->v[i].uv.x) )
132 && ( NearlyEqual(ep->v[j].uv.y,ep2->v[i].uv.y) )
133 )
134 {
135 common2=j;
136 }
137 }
138
139 if (common2==-1) ep2_notcommon=i;
140
141 if (common==-1) ep_notcommon=i;
142 }
143
144 if ((count>=2) && (ep_notcommon!=-1) && (ep2_notcommon!=-1))
145 {
146 ep2->type |= POLY_QUAD;
147
148 switch (ep2_notcommon)
149 {
150 case 1:
151 CopyVertices(ep2,3,0);
152 CopyVertices(ep2,0,1);
153 CopyVertices(ep2,1,2);
154 CopyVertices(ep2,2,3);
155 break;
156
157 case 2:
158 CopyVertices(ep2,3,0);
159 CopyVertices(ep2,0,2);
160 CopyVertices(ep2,2,1);
161 CopyVertices(ep2,1,3);
162
163 break;
164 }
165
166 CopyVertices(ep2,3,0);
167 ep2->v[3].p = ep->v[ep_notcommon].p;
168 ep2->tv[3].uv = ep2->v[3].uv = ep->v[ep_notcommon].uv;
169 ep2->tv[3].color = ep2->v[3].color = Color::white.toBGR();
170 ep2->tv[3].rhw = ep2->v[3].rhw = 1.f;
171
172 DeclareEGInfo(ep->v[3].p.x, ep->v[3].p.z);
173
174 ep2->center = (ep2->v[0].p + ep2->v[1].p + ep2->v[2].p + ep2->v[3].p) * 0.25f;
175 ep2->max = componentwise_max(ep2->max, ep2->v[3].p);
176 ep2->min = componentwise_min(ep2->min, ep2->v[3].p);
177
178 ep2->norm2 = ep->norm;
179
180 ep2->area += fdist((ep2->v[1].p + ep2->v[2].p) * .5f, ep2->v[3].p)
181 * fdist(ep2->v[3].p, ep2->v[1].p)*.5f; // should this be v[2] instead of v[3]?
182
183 return true;
184 }
185
186 return false;
187 }
188
189 #define TYPE_ROOM 2
TryToQuadify(EERIEPOLY * ep,EERIE_3DOBJ * eobj)190 bool TryToQuadify(EERIEPOLY * ep,EERIE_3DOBJ * eobj)
191 {
192 long posx,posz;
193 float cx,cz;
194 EERIE_BKG_INFO * eg;
195 cx=(ep->v[0].p.x+ep->v[1].p.x+ep->v[2].p.x);
196 cz=(ep->v[0].p.z+ep->v[1].p.z+ep->v[2].p.z);
197 posx = cx*( 1.0f / 3 )*ACTIVEBKG->Xmul;
198 posz = cz*( 1.0f / 3 )*ACTIVEBKG->Zmul;
199
200 long dx,dz,fx,fz;
201 dx=std::max(0L,posx-1);
202 fx=std::min(posx+1,ACTIVEBKG->Xsize-1L);
203 dz=std::max(0L,posz-1);
204 fz=std::min(posz+1,ACTIVEBKG->Zsize-1L);
205 float tolerance=0.1f;
206
207 for (long kl = 0; kl < 2; kl++)
208 for (long zz=dz;zz<=fz;zz++)
209 for (long xx=dx;xx<=fx;xx++)
210 {
211 long val1 = 0;
212
213 long type, val2;
214 if (!GetNameInfo(eobj->name, type, val1, val2))
215 return false;
216
217 if (type!=TYPE_ROOM)
218 return false;
219
220 eg=(EERIE_BKG_INFO *)&ACTIVEBKG->Backg[xx+zz*ACTIVEBKG->Xsize];
221
222 if (eg)
223 for (long n=0;n<eg->nbpoly;n++)
224 {
225 EERIEPOLY * ep2=(EERIEPOLY *)&eg->polydata[n];
226
227 if (ep2->room!=val1) continue;
228
229 if (ep==ep2) continue;
230
231 if ((kl==0) && (ep2->type & POLY_QUAD) )
232 {
233 if (Quadable(ep,ep2,tolerance)) return true;
234 }
235 else if ((kl==1) && !(ep2->type & POLY_QUAD) )
236 {
237 if (Quadable(ep,ep2,tolerance)) return true;
238 }
239 }
240 }
241
242 return false;
243 }
244
245 CircularVertexBuffer<TexturedVertex> * pDynamicVertexBuffer_TLVERTEX;
246
EERIEDRAWPRIM(Renderer::Primitive primitive,const TexturedVertex * vertices,size_t count,bool nocount)247 void EERIEDRAWPRIM(Renderer::Primitive primitive, const TexturedVertex * vertices, size_t count, bool nocount) {
248
249 if(!nocount) {
250 EERIEDrawnPolys++;
251 }
252
253 pDynamicVertexBuffer_TLVERTEX->draw(primitive, vertices, count);
254 }
255
Delayed_FlushAll()256 void Delayed_FlushAll() {
257
258 TextureContainer* ptcTexture = GetTextureList();
259
260 while( ptcTexture )
261 {
262 if ((ptcTexture->delayed_nb) && ptcTexture->delayed)
263 {
264 long to;
265
266 if (ViewMode & VIEWMODE_FLAT)
267 GRenderer->ResetTexture(0);
268 else
269 GRenderer->SetTexture(0, ptcTexture);
270
271 DELAYED_PRIM * del=(DELAYED_PRIM *)ptcTexture->delayed;
272
273 for (long i=0;i<ptcTexture->delayed_nb;i++)
274 {
275 EERIEPOLY * ep=del[i].data;
276
277 if (!(ep->type & POLY_DOUBLESIDED))
278 GRenderer->SetCulling(Renderer::CullCW);
279 else
280 GRenderer->SetCulling(Renderer::CullNone);
281
282 if (ep->type & POLY_QUAD)
283 to=4;
284 else to=3;
285
286 EERIEDRAWPRIM(Renderer::TriangleStrip, ep->tv, to, true);
287
288 if ( ptcTexture->userflags & POLY_METAL)
289 {
290 GRenderer->SetBlendFunc(Renderer::BlendDstColor, Renderer::BlendOne);
291 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
292 GRenderer->ResetTexture(0);
293
294 EERIEDRAWPRIM(Renderer::TriangleStrip, ep->tv, to);
295 }
296
297 if ( (ep->type & POLY_LAVA) || (ep->type & POLY_WATER) )
298 {
299 GRenderer->SetBlendFunc(Renderer::BlendDstColor, Renderer::BlendOne);
300 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
301 TexturedVertex verts[4];
302 GRenderer->SetTexture(0, enviro);
303
304 for(long i=0;i<to;i++) {
305
306 verts[i].p = ep->tv[i].p;
307 verts[i].rhw = ep->tv[i].rhw;
308 verts[i].color = 0xFFFFFFFF;
309
310 // Water
311 if (ep->type & POLY_LAVA)
312 {
313 verts[i].uv.x=ep->v[i].p.x*( 1.0f / 1000 )+EEsin((ep->v[i].p.x)*( 1.0f / 200 )+(float)arxtime.get_frame_time()*( 1.0f / 2000 ))*( 1.0f / 20 );
314 verts[i].uv.y=ep->v[i].p.z*( 1.0f / 1000 )+EEcos((ep->v[i].p.z)*( 1.0f / 200 )+(float)arxtime.get_frame_time()*( 1.0f / 2000 ))*( 1.0f / 20 );
315 }
316 else
317 {
318 GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
319 verts[i].uv.x=ep->v[i].p.x*( 1.0f / 800 )+EEsin((ep->v[i].p.x)*( 1.0f / 600 )+(float)arxtime.get_frame_time()*( 1.0f / 1000 ))*( 1.0f / 9 );
320 verts[i].uv.y=ep->v[i].p.z*( 1.0f / 800 )+EEcos((ep->v[i].p.z)*( 1.0f / 600 )+(float)arxtime.get_frame_time()*( 1.0f / 1000 ))*( 1.0f / 9 );
321
322 if (ep->type & POLY_FALL) verts[i].uv.y-=(float)(arxtime.get_frame_time())*( 1.0f / 200 );
323 }
324 }
325
326 EERIEDRAWPRIM(Renderer::TriangleStrip, verts, to, true);
327
328 if (ep->type & POLY_WATER)
329 {
330 for (long i=0;i<to;i++)
331 {
332 verts[i].uv.x=ep->v[i].p.x*( 1.0f / 1000 )+EEsin((ep->v[i].p.y)*( 1.0f / 200 )+(float)arxtime.get_frame_time()*( 1.0f / 600 )*( 1.0f / 3 ))*( 1.0f / 10 );
333 verts[i].uv.y=ep->v[i].p.z*( 1.0f / 1000 )+EEcos((ep->v[i].p.z+ep->v[i].p.x)*( 1.0f / 200 )+(float)arxtime.get_frame_time()*( 1.0f / 600 )*( 1.0f / 3 ))*( 1.0f / 10 );
334
335 if (ep->type & POLY_FALL)
336 {
337 verts[i].uv.y-=(float)(arxtime.get_frame_time())*( 1.0f / 200 );
338 }
339 }
340
341 EERIEDRAWPRIM(Renderer::TriangleStrip, verts, to);
342 }
343
344 if (ep->type & POLY_LAVA)
345 {
346 for (long i=0;i<to;i++)
347 {
348 verts[i].uv.x=ep->v[i].p.x*( 1.0f / 1000 )+EEsin((ep->v[i].p.x)*( 1.0f / 100 )+(float)arxtime.get_frame_time()*( 1.0f / 2000 ))*( 1.0f / 10 );
349 verts[i].uv.y=ep->v[i].p.z*( 1.0f / 1000 )+EEcos((ep->v[i].p.z)*( 1.0f / 100 )+(float)arxtime.get_frame_time()*( 1.0f / 2000 ))*( 1.0f / 10 );
350 }
351 EERIEDRAWPRIM(Renderer::TriangleStrip, verts, to);
352 for ( int i=0;i<to;i++)
353 {
354 verts[i].uv.x=ep->v[i].p.x*( 1.0f / 600 )+EEsin((ep->v[i].p.x)*( 1.0f / 160 )+(float)arxtime.get_frame_time()*( 1.0f / 2000 ))*( 1.0f / 11 );
355 verts[i].uv.y=ep->v[i].p.z*( 1.0f / 600 )+EEcos((ep->v[i].p.z)*( 1.0f / 160 )+(float)arxtime.get_frame_time()*( 1.0f / 2000 ))*( 1.0f / 11 );
356 verts[i].color=0xFF666666;
357 }
358
359 GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor);
360 EERIEDRAWPRIM(Renderer::TriangleStrip, verts, to);
361 }
362 }
363
364 GRenderer->SetTexture(0, ptcTexture);
365 GRenderer->SetRenderState(Renderer::AlphaBlending, false);
366 }
367
368 if (ZMAPMODE)
369 {
370 if (ptcTexture->TextureRefinement==NULL)
371 ptcTexture->delayed_nb=0;
372
373 if (ptcTexture->delayed_nb)
374 {
375 GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor);
376 GRenderer->SetRenderState(Renderer::DepthWrite, false);
377 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
378 TexturedVertex verts[4];
379 GRenderer->SetTexture(0, ptcTexture->TextureRefinement);
380
381 for (long i=0;i<ptcTexture->delayed_nb;i++)
382 {
383 DELAYED_PRIM * del=(DELAYED_PRIM *)ptcTexture->delayed;
384 EERIEPOLY * ep=del[i].data;
385
386 if (ep->type & POLY_QUAD)
387 {
388 if ( (ep->tv[0].p.z>0.048f)
389 && (ep->tv[1].p.z>0.048f)
390 && (ep->tv[2].p.z>0.048f)
391 && (ep->tv[3].p.z > 0.048f)) continue;
392
393 to=4;
394 }
395 else
396 {
397 if ( (ep->tv[0].p.z>0.048f)
398 && (ep->tv[1].p.z>0.048f)
399 && (ep->tv[2].p.z > 0.048f)) continue;
400
401 to=3;
402 }
403
404 if (!(ep->type & POLY_DOUBLESIDED))
405 GRenderer->SetCulling(Renderer::CullCW);
406 else GRenderer->SetCulling(Renderer::CullNone);
407
408
409 long tmp;
410
411 for(long j = 0; j < to; j++) {
412
413 verts[j].p = ep->tv[j].p;
414 verts[j].uv = ep->tv[j].uv * 4.f;
415 verts[j].rhw = ep->tv[j].rhw;
416
417 float val = (0.038f - verts[j].p.z);
418 if (val<=0.f)
419 {
420 verts[j].color=0xFF000000;
421 }
422 else
423 {
424 if (val>0.0175)
425 {
426 verts[j].color=0xFFB2B2B2;
427 }
428 else
429 {
430 tmp = val*10200;
431 verts[j].color=0xFF000000 | (tmp<<16) | (tmp<<8) | tmp;
432 }
433 }
434 }
435
436 EERIEDRAWPRIM(Renderer::TriangleStrip, verts, to, true);
437 }
438 }
439
440 EERIEDrawnPolys+=ptcTexture->delayed_nb;
441 GRenderer->SetRenderState(Renderer::AlphaBlending, false);
442 GRenderer->SetRenderState(Renderer::DepthWrite, true);
443 }
444
445 EERIEDrawnPolys+=ptcTexture->delayed_nb;
446 ptcTexture->delayed_nb=0;
447 }
448
449 ptcTexture = ptcTexture->m_pNext;
450 }
451 }
452
Delayed_EERIEDRAWPRIM(EERIEPOLY * ep)453 void Delayed_EERIEDRAWPRIM( EERIEPOLY * ep)
454 {
455 TextureContainer * tc=ep->tex;
456
457 if (!tc) return;
458
459 if (tc->delayed_nb>=tc->delayed_max)
460 {
461 tc->delayed=(DELAYED_PRIM *)realloc(tc->delayed,sizeof(DELAYED_PRIM)*(tc->delayed_nb+1));
462 tc->delayed_max=tc->delayed_nb+1;
463 }
464
465 DELAYED_PRIM * del=(DELAYED_PRIM *)tc->delayed;
466 del[tc->delayed_nb].data=ep;
467 tc->delayed_nb++;
468 }
469
EERIEDraw2DLine(float x0,float y0,float x1,float y1,float z,Color col)470 void EERIEDraw2DLine(float x0, float y0, float x1, float y1, float z, Color col) {
471
472 TexturedVertex v[2];
473 v[0].p.x = x0;
474 v[0].p.y = y0;
475 v[0].p.z = v[1].p.z = z;
476 v[1].p.x = x1;
477 v[1].p.y = y1;
478 v[1].color = v[0].color = col.toBGRA();
479 v[1].rhw = v[0].rhw = 1.f;
480
481 GRenderer->ResetTexture(0);
482 EERIEDRAWPRIM(Renderer::LineList, v, 2);
483 }
484
EERIEDraw2DRect(float x0,float y0,float x1,float y1,float z,Color col)485 void EERIEDraw2DRect(float x0, float y0, float x1, float y1, float z, Color col) {
486
487 TexturedVertex v[5];
488 v[4].p.x = v[3].p.x = v[0].p.x = x0;
489 v[4].p.y = v[1].p.y = v[0].p.y = y0;
490 v[2].p.x = v[1].p.x = x1;
491 v[3].p.y = v[2].p.y = y1;
492 v[4].p.z = v[3].p.z = v[2].p.z = v[1].p.z = v[0].p.z = z;
493 v[4].color = v[3].color = v[2].color = v[1].color = v[0].color = col.toBGRA();
494 v[4].rhw = v[3].rhw = v[2].rhw = v[1].rhw = v[0].rhw = 1.f;
495
496 GRenderer->ResetTexture(0);
497 EERIEDRAWPRIM(Renderer::LineStrip, v, 5);
498 }
499
EERIEDrawFill2DRectDegrad(float x0,float y0,float x1,float y1,float z,Color cold,Color cole)500 void EERIEDrawFill2DRectDegrad(float x0, float y0, float x1, float y1, float z, Color cold, Color cole) {
501
502 TexturedVertex v[4];
503 v[0].p.x = v[2].p.x = x0;
504 v[0].p.y = v[1].p.y = y0;
505 v[1].p.x = v[3].p.x = x1;
506 v[2].p.y = v[3].p.y = y1;
507 v[0].color = v[1].color = cold.toBGRA();
508 v[2].color = v[3].color = cole.toBGRA();
509 v[0].p.z = v[1].p.z = v[2].p.z = v[3].p.z = z;
510 v[3].rhw = v[2].rhw = v[1].rhw = v[0].rhw = 1.f;
511
512 GRenderer->ResetTexture(0);
513 EERIEDRAWPRIM(Renderer::TriangleStrip, v, 4);
514 }
515
EERIEDraw3DCylinder(const EERIE_CYLINDER & cyl,Color col)516 void EERIEDraw3DCylinder(const EERIE_CYLINDER & cyl, Color col) {
517
518 #define STEPCYL 16
519 for(long i = 0; i < 360 - STEPCYL; i += STEPCYL) {
520
521 float es = sin(radians(MAKEANGLE((float)i))) * cyl.radius;
522 float ec = cos(radians(MAKEANGLE((float)i))) * cyl.radius;
523 float es2 = sin(radians(MAKEANGLE((float)(i + STEPCYL)))) * cyl.radius;
524 float ec2 = cos(radians(MAKEANGLE((float)(i + STEPCYL)))) * cyl.radius;
525
526 // Draw low pos
527 EERIEDraw3DLine(cyl.origin + Vec3f(es, 0.f, ec), cyl.origin + Vec3f(es2, 0.f, ec2), col);
528 // Draw vertical
529 Vec3f from = cyl.origin + Vec3f(es, 0.f, ec);
530 EERIEDraw3DLine(from, from + Vec3f(0.f, cyl.height, 0.f), col);
531 // Draw high pos
532 Vec3f from2 = cyl.origin + Vec3f(es, cyl.height, ec);
533 Vec3f to = cyl.origin + Vec3f(es2, cyl.height, ec2);
534 EERIEDraw3DLine(from2, to, col);
535 }
536 }
537
EERIEDraw3DCylinderBase(const EERIE_CYLINDER & cyl,Color col)538 void EERIEDraw3DCylinderBase(const EERIE_CYLINDER & cyl, Color col) {
539
540 #define STEPCYL 16
541 for(long i = 0; i < 360 - STEPCYL; i += STEPCYL) {
542
543 float es = sin(radians(MAKEANGLE((float)i))) * cyl.radius;
544 float ec = cos(radians(MAKEANGLE((float)i))) * cyl.radius;
545 float es2 = sin(radians(MAKEANGLE((float)(i + STEPCYL)))) * cyl.radius;
546 float ec2 = cos(radians(MAKEANGLE((float)(i + STEPCYL)))) * cyl.radius;
547
548 // Draw low pos
549 EERIEDraw3DLine(cyl.origin + Vec3f(es, 0.f, ec), cyl.origin + Vec3f(es2, 0.f, ec2), col);
550 }
551 }
552
EERIEDrawCircle(float x0,float y0,float r,Color col,float z)553 void EERIEDrawCircle(float x0, float y0, float r, Color col, float z) {
554
555 float lx = x0;
556 float ly = y0 + r;
557 GRenderer->ResetTexture(0);
558
559 for(long i = 0; i < 361; i += 10) {
560 float t = radians((float)i);
561 float x = x0 - sin(t) * r;
562 float y = y0 + cos(t) * r;
563 EERIEDraw2DLine(lx, ly, x, y, z, col);
564 lx = x;
565 ly = y;
566 }
567 }
568
569 //*************************************************************************************
570 //*************************************************************************************
571
EERIEDrawTrue3DLine(const Vec3f & orgn,const Vec3f & dest,Color col)572 void EERIEDrawTrue3DLine(const Vec3f & orgn, const Vec3f & dest, Color col) {
573
574 Vec3f vect = dest - orgn;
575 float m = ffsqrt(vect.lengthSqr());
576
577 if (m<=0) return;
578
579 vect *= 1 / m;
580
581 Vec3f cpos = orgn;
582
583 while (m>0)
584 {
585 float dep=std::min(m,30.f);
586 Vec3f tpos = cpos + (vect * dep);
587 EERIEDraw3DLine(cpos, tpos, col);
588 cpos = tpos;
589 m-=dep;
590 }
591 }
592 //*************************************************************************************
593 //*************************************************************************************
594
EERIEDraw3DLine(const Vec3f & orgn,const Vec3f & dest,Color col)595 void EERIEDraw3DLine(const Vec3f & orgn, const Vec3f & dest, Color col) {
596
597 TexturedVertex v[2];
598 TexturedVertex in;
599
600 in.p = orgn;
601 EE_RTP(&in,&v[0]);
602 if(v[0].p.z < 0.f) {
603 return;
604 }
605
606 in.p = dest;
607 EE_RTP(&in,&v[1]);
608 if(v[1].p.z<0.f) {
609 return;
610 }
611
612 GRenderer->ResetTexture(0);
613 v[1].color = v[0].color = col.toBGRA();
614
615 EERIEDRAWPRIM(Renderer::LineList, v, 2);
616 }
617 #define BASICFOCAL 350.f
618 //*************************************************************************************
619 //*************************************************************************************
620
EERIEDrawSprite(TexturedVertex * in,float siz,TextureContainer * tex,Color color,float Zpos)621 void EERIEDrawSprite(TexturedVertex * in, float siz, TextureContainer * tex, Color color, float Zpos) {
622
623 TexturedVertex out;
624
625 EERIETreatPoint2(in,&out);
626
627 if ((out.p.z>0.f) && (out.p.z<1000.f)
628 && (out.p.x>-1000) && (out.p.x<2500.f)
629 && (out.p.y>-500) && (out.p.y<1800.f))
630 {
631 float use_focal=BASICFOCAL*Xratio;
632 float t;
633
634 if (siz < 0)
635 {
636 t=-siz;
637 }
638 else
639 {
640 t=siz*((out.rhw-1.f)*use_focal*0.001f);
641
642 if (t<=0.f) t=0.00000001f;
643 }
644
645 if (Zpos<=1.f)
646 {
647 out.p.z = Zpos;
648 out.rhw=1.f-out.p.z;
649 }
650 else
651 {
652 out.rhw*=(1.f/3000.f);
653 }
654
655 SPRmaxs.x=out.p.x+t;
656 SPRmins.x=out.p.x-t;
657 SPRmaxs.y=out.p.y+t;
658 SPRmins.y=out.p.y-t;
659
660 ColorBGRA col = color.toBGRA();
661 TexturedVertex v[4];
662 v[0] = TexturedVertex(Vec3f(SPRmins.x, SPRmins.y, out.p.z), out.rhw, col, out.specular, Vec2f::ZERO);
663 v[1] = TexturedVertex(Vec3f(SPRmaxs.x, SPRmins.y, out.p.z), out.rhw, col, out.specular, Vec2f::X_AXIS);
664 v[2] = TexturedVertex(Vec3f(SPRmins.x, SPRmaxs.y, out.p.z), out.rhw, col, out.specular, Vec2f::Y_AXIS);
665 v[3] = TexturedVertex(Vec3f(SPRmaxs.x, SPRmaxs.y, out.p.z), out.rhw, col, out.specular, Vec2f(1.f, 1.f));
666
667 GRenderer->SetTexture(0, tex);
668 EERIEDRAWPRIM(Renderer::TriangleStrip, v, 4);
669 }
670 else SPRmaxs.x=-1;
671 }
672
673 //*************************************************************************************
674 //*************************************************************************************
675
EERIEDrawRotatedSprite(TexturedVertex * in,float siz,TextureContainer * tex,Color color,float Zpos,float rot)676 void EERIEDrawRotatedSprite(TexturedVertex * in, float siz, TextureContainer * tex, Color color,
677 float Zpos, float rot) {
678
679 TexturedVertex out;
680 EERIETreatPoint2(in, &out);
681
682 if ((out.p.z>0.f) && (out.p.z<1000.f))
683 {
684 float use_focal=BASICFOCAL*Xratio;
685
686 float t = siz * ((out.rhw - 1.f) * use_focal * 0.001f);
687
688 if (t<=0.f) t=0.00000001f;
689
690 if (Zpos<=1.f)
691 {
692 out.p.z = Zpos;
693 out.rhw=1.f-out.p.z;
694 }
695 else
696 {
697 out.rhw*=(1.f/3000.f);
698 }
699
700 ColorBGRA col = color.toBGRA();
701 TexturedVertex v[4];
702 v[0] = TexturedVertex(Vec3f(0, 0, out.p.z), out.rhw, col, out.specular, Vec2f::ZERO);
703 v[1] = TexturedVertex(Vec3f(0, 0, out.p.z), out.rhw, col, out.specular, Vec2f::X_AXIS);
704 v[2] = TexturedVertex(Vec3f(0, 0, out.p.z), out.rhw, col, out.specular, Vec2f(1.f, 1.f));
705 v[3] = TexturedVertex(Vec3f(0, 0, out.p.z), out.rhw, col, out.specular, Vec2f::Y_AXIS);
706
707
708 SPRmaxs.x=out.p.x+t;
709 SPRmins.x=out.p.x-t;
710
711 SPRmaxs.y=out.p.y+t;
712 SPRmins.y=out.p.y-t;
713
714 SPRmaxs.z = SPRmins.z = out.p.z;
715
716 for(long i=0;i<4;i++) {
717 float tt = radians(MAKEANGLE(rot+90.f*i+45+90));
718 v[i].p.x = EEsin(tt) * t + out.p.x;
719 v[i].p.y = EEcos(tt) * t + out.p.y;
720 }
721
722 GRenderer->SetTexture(0, tex);
723 EERIEDRAWPRIM(Renderer::TriangleFan, v, 4);
724 }
725 else SPRmaxs.x=-1;
726 }
727
728 //*************************************************************************************
729 //*************************************************************************************
730
EERIEPOLY_DrawWired(EERIEPOLY * ep,Color color)731 void EERIEPOLY_DrawWired(EERIEPOLY * ep, Color color) {
732
733 TexturedVertex ltv[5];
734 ltv[0] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f::ZERO);
735 ltv[1] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f::X_AXIS);
736 ltv[2] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f(1.f, 1.f));
737 ltv[3] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f::Y_AXIS);
738 ltv[4] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f::Y_AXIS);
739
740 long to;
741
742 if (ep->type & POLY_QUAD) to=4;
743 else to=3;
744
745 memcpy(ltv,ep->tv,sizeof(TexturedVertex)*to);
746 ltv[0].p.z-=0.0002f;
747 ltv[1].p.z-=0.0002f;
748 ltv[2].p.z-=0.0002f;
749 ltv[3].p.z-=0.0002f;
750
751 if (to==4)
752 {
753 memcpy(<v[2],&ep->tv[3],sizeof(TexturedVertex));
754 memcpy(<v[3],&ep->tv[2],sizeof(TexturedVertex));
755 memcpy(<v[4],&ep->tv[0],sizeof(TexturedVertex));
756 ltv[4].p.z-=0.0002f;
757 }
758 else memcpy(<v[to],<v[0],sizeof(TexturedVertex));
759
760 GRenderer->ResetTexture(0);
761
762 ColorBGRA col = color.toBGRA();
763 if (col)
764 ltv[0].color=ltv[1].color=ltv[2].color=ltv[3].color=ltv[4].color=col;
765 else if (to==4)
766 ltv[0].color=ltv[1].color=ltv[2].color=ltv[3].color=ltv[4].color=0xFF00FF00;
767 else ltv[0].color=ltv[1].color=ltv[2].color=ltv[3].color=0xFFFFFF00;
768
769 EERIEDRAWPRIM(Renderer::LineStrip, ltv, to + 1);
770 }
771
EERIEPOLY_DrawNormals(EERIEPOLY * ep)772 void EERIEPOLY_DrawNormals(EERIEPOLY * ep) {
773 TexturedVertex ltv[5];
774 ltv[0] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f::ZERO);
775 ltv[1] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f::X_AXIS);
776 ltv[2] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f(1.f, 1.f));
777 ltv[3] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f::Y_AXIS);
778 ltv[4] = TexturedVertex(Vec3f(0, 0, 0.5), 1.f, 1, 1, Vec2f::Y_AXIS);
779
780 TexturedVertex lv;
781 long to;
782
783 if (ep->type & POLY_QUAD) to=4;
784 else to=3;
785
786 lv.p = ep->center;
787 EE_RTP(&lv,<v[0]);
788 lv.p += ep->norm * 10.f;
789 EE_RTP(&lv,<v[1]);
790 GRenderer->ResetTexture(0);
791 ltv[1].color=ltv[0].color=0xFFFF0000;
792
793 if ((ltv[1].p.z>0.f) && (ltv[0].p.z>0.f))
794 EERIEDRAWPRIM(Renderer::LineList, ltv, 3);
795
796 for(long h = 0; h < to; h++) {
797 lv.p = ep->v[h].p;
798 EE_RTP(&lv,<v[0]);
799 lv.p += ep->nrml[h] * 10.f;
800 EE_RTP(&lv,<v[1]);
801 GRenderer->ResetTexture(0);
802 ltv[1].color=ltv[0].color=Color::yellow.toBGR();
803
804 if ((ltv[1].p.z>0.f) && (ltv[0].p.z>0.f))
805 EERIEDRAWPRIM(Renderer::LineList, ltv, 3);
806 }
807 }
808
809
810 //-----------------------------------------------------------------------------
811
EERIEDrawBitmap(float x,float y,float sx,float sy,float z,TextureContainer * tex,Color color)812 void EERIEDrawBitmap(float x, float y, float sx, float sy, float z, TextureContainer * tex, Color color) {
813
814 // Match pixel and texel origins.
815 x -= .5f, y -= .5f;
816
817 Vec2f uv = (tex) ? tex->uv : Vec2f::ZERO;
818
819 ColorBGRA col = color.toBGRA();
820 TexturedVertex v[4];
821 v[0] = TexturedVertex(Vec3f(x, y, z), 1.f, col, 0xff000000, Vec2f(0.f, 0.f));
822 v[1] = TexturedVertex(Vec3f(x + sx, y, z), 1.f, col, 0xff000000, Vec2f(uv.x, 0.f));
823 v[2] = TexturedVertex(Vec3f(x, y + sy, z), 1.f, col, 0xff000000, Vec2f(0.f, uv.y));
824 v[3] = TexturedVertex(Vec3f(x + sx, y + sy, z), 1.f, col, 0xff000000, Vec2f(uv.x, uv.y));
825
826 GRenderer->SetTexture(0, tex);
827 EERIEDRAWPRIM(Renderer::TriangleStrip, v, 4);
828 }
829
EERIEDrawBitmap_uv(float x,float y,float sx,float sy,float z,TextureContainer * tex,Color color,float u0,float v0,float u1,float v1)830 void EERIEDrawBitmap_uv(float x, float y, float sx, float sy, float z, TextureContainer * tex,
831 Color color, float u0, float v0, float u1, float v1) {
832
833 // Match pixel and texel origins.
834 x -= .5f, y -= .5f;
835
836 Vec2f uv = (tex) ? tex->uv : Vec2f::ONE;
837 u0 *= uv.x, u1 *= uv.x, v0 *= uv.y, v1 *= uv.y;
838
839 ColorBGRA col = color.toBGRA();
840 TexturedVertex v[4];
841 v[0] = TexturedVertex(Vec3f(x, y, z), 1.f, col, 0xff000000, Vec2f(u0, v0));
842 v[1] = TexturedVertex(Vec3f(x + sx, y, z), 1.f, col, 0xff000000, Vec2f(u1, v0));
843 v[2] = TexturedVertex(Vec3f(x + sx, y + sy, z), 1.f, col, 0xff000000, Vec2f(u1, v1));
844 v[3] = TexturedVertex(Vec3f(x, y + sy, z), 1.f, col, 0xff000000, Vec2f(u0, v1));
845
846 GRenderer->SetTexture(0, tex);
847 EERIEDRAWPRIM(Renderer::TriangleFan, v, 4);
848 }
849
EERIEDrawBitmapUVs(float x,float y,float sx,float sy,float z,TextureContainer * tex,Color color,float u0,float v0,float u1,float v1,float u2,float v2,float u3,float v3)850 void EERIEDrawBitmapUVs(float x, float y, float sx, float sy, float z, TextureContainer * tex,
851 Color color, float u0, float v0, float u1, float v1, float u2, float v2,
852 float u3, float v3) {
853
854 // Match pixel and texel origins.
855 x -= .5f, y -= .5f;
856
857 ColorBGRA col = color.toBGRA();
858 TexturedVertex v[4];
859 v[0] = TexturedVertex(Vec3f(x, y, z), 1.f, col, 0xff000000, Vec2f(u0, v0));
860 v[1] = TexturedVertex(Vec3f(x + sx, y, z), 1.f, col, 0xff000000, Vec2f(u1, v1));
861 v[2] = TexturedVertex(Vec3f(x, y + sy, z), 1.f, col, 0xff000000, Vec2f(u2, v2));
862 v[3] = TexturedVertex(Vec3f(x + sx, y + sy, z), 1.f, col, 0xff000000, Vec2f(u3, v3));
863
864 GRenderer->SetTexture(0, tex);
865 EERIEDRAWPRIM(Renderer::TriangleStrip, v, 4);
866 }
867
EERIEDrawBitmap2(float x,float y,float sx,float sy,float z,TextureContainer * tex,Color color)868 void EERIEDrawBitmap2(float x, float y, float sx, float sy, float z, TextureContainer * tex, Color color) {
869
870 // Match pixel and texel origins.
871 x -= .5f, y -= .5f;
872
873 Vec2f uv = (tex) ? tex->uv : Vec2f::ZERO;
874
875 ColorBGRA col = color.toBGRA();
876 TexturedVertex v[4];
877 float rhw = 1.f - z;
878 v[0] = TexturedVertex(Vec3f(x, y, z), rhw, col, 0xFF000000, Vec2f(0.f, 0.f));
879 v[1] = TexturedVertex(Vec3f(x + sx, y, z), rhw, col, 0xFF000000, Vec2f(uv.x, 0.f));
880 v[2] = TexturedVertex(Vec3f(x, y + sy, z), rhw, col, 0xFF000000, Vec2f(0.f, uv.y));
881 v[3] = TexturedVertex(Vec3f(x + sx, y + sy, z), rhw, col, 0xFF000000, Vec2f(uv.x, uv.y));
882
883 GRenderer->SetTexture(0, tex);
884
885 if(tex && tex->hasColorKey()) {
886 GRenderer->SetAlphaFunc(Renderer::CmpGreater, .5f);
887 }
888
889 EERIEDRAWPRIM(Renderer::TriangleStrip, v, 4);
890
891 if(tex && tex->hasColorKey()) {
892 GRenderer->SetAlphaFunc(Renderer::CmpNotEqual, 0.f);
893 }
894 }
895
EERIEDrawBitmap2DecalY(float x,float y,float sx,float sy,float z,TextureContainer * tex,Color color,float _fDeltaY)896 void EERIEDrawBitmap2DecalY(float x, float y, float sx, float sy, float z, TextureContainer * tex,
897 Color color, float _fDeltaY) {
898
899 // Match pixel and texel origins.
900 x -= .5f, y -= .5f;
901
902 Vec2f uv = (tex) ? tex->uv : Vec2f::ZERO;
903 float sv = uv.y * _fDeltaY;
904
905 ColorBGRA col = color.toBGRA();
906 TexturedVertex v[4];
907 float fDy = _fDeltaY * sy;
908 if(sx < 0) {
909 v[0] = TexturedVertex(Vec3f(x, y + fDy, z), 1.f, col, 0xFF000000, Vec2f(uv.x, sv));
910 v[1] = TexturedVertex(Vec3f(x - sx, y + fDy, z), 1.f, col, 0xFF000000, Vec2f(0.f, sv));
911 v[2] = TexturedVertex(Vec3f(x - sx, y + sy, z), 1.f, col, 0xFF000000, Vec2f(0.f, uv.y));
912 v[3] = TexturedVertex(Vec3f(x, y + sy, z), 1.f, col, 0xFF000000, Vec2f(uv.x, uv.y));
913 } else {
914 v[0] = TexturedVertex(Vec3f(x, y + fDy, z), 1.f, col, 0xFF000000, Vec2f(0.f, sv));
915 v[1] = TexturedVertex(Vec3f(x + sx, y + fDy, z), 1.f, col, 0xFF000000, Vec2f(uv.x, sv));
916 v[2] = TexturedVertex(Vec3f(x + sx, y + sy, z), 1.f, col, 0xFF000000, Vec2f(uv.x, uv.y));
917 v[3] = TexturedVertex(Vec3f(x, y + sy, z), 1.f, col, 0xFF000000, Vec2f(0.f, uv.y));
918 }
919
920 GRenderer->SetTexture(0, tex);
921 EERIEDRAWPRIM(Renderer::TriangleFan, v, 4);
922 }
923