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(&ltv[2],&ep->tv[3],sizeof(TexturedVertex));
754 		memcpy(&ltv[3],&ep->tv[2],sizeof(TexturedVertex));
755 		memcpy(&ltv[4],&ep->tv[0],sizeof(TexturedVertex));
756 		ltv[4].p.z-=0.0002f;
757 	}
758 	else memcpy(&ltv[to],&ltv[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,&ltv[0]);
788 	lv.p += ep->norm * 10.f;
789 	EE_RTP(&lv,&ltv[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,&ltv[0]);
799 		lv.p += ep->nrml[h] * 10.f;
800 		EE_RTP(&lv,&ltv[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