20 |
20 |
21 unit uRender; |
21 unit uRender; |
22 |
22 |
23 interface |
23 interface |
24 |
24 |
25 uses SDLh, uTypes, GLunit, uConsts, uTextures; |
25 uses SDLh, uTypes, GLunit, uConsts, uTextures, math; |
|
26 |
|
27 procedure initModule; |
26 |
28 |
27 procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt); |
29 procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt); |
28 procedure DrawSprite (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt); |
30 procedure DrawSprite (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt); |
29 procedure DrawSpriteFromRect (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); |
31 procedure DrawSpriteFromRect (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); |
30 procedure DrawSpriteClipped (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt); |
32 procedure DrawSpriteClipped (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt); |
49 procedure DrawScreenWidget (widget: POnScreenWidget); |
51 procedure DrawScreenWidget (widget: POnScreenWidget); |
50 |
52 |
51 procedure Tint (r, g, b, a: Byte); inline; |
53 procedure Tint (r, g, b, a: Byte); inline; |
52 procedure Tint (c: Longword); inline; |
54 procedure Tint (c: Longword); inline; |
53 |
55 |
|
56 // This is just temporary and becomes non public once everything changed to GL2 |
|
57 procedure UpdateModelview; |
|
58 procedure ResetModelview; |
|
59 procedure SetOffset(X, Y: Longint); |
|
60 procedure ResetRotation; |
|
61 |
54 |
62 |
55 implementation |
63 implementation |
56 uses uVariables; |
64 uses uVariables; |
57 |
65 |
58 var LastTint: LongWord = 0; |
66 var LastTint: LongWord = 0; |
|
67 Modelview: TMatrix4x4f; |
|
68 |
|
69 const DegToRad = 0.01745329252; // 2PI / 360 |
|
70 |
|
71 procedure UpdateModelview; |
|
72 begin |
|
73 glLoadMatrixf(@Modelview[0,0]); |
|
74 end; |
|
75 |
|
76 procedure ResetModelview; |
|
77 begin |
|
78 Modelview[0,0]:= 1.0; Modelview[1,0]:=0.0; Modelview[3,0]:= 0; |
|
79 Modelview[0,1]:= 0.0; Modelview[1,1]:=1.0; Modelview[3,1]:= 0; |
|
80 UpdateModelview; |
|
81 end; |
|
82 |
|
83 procedure SetOffset(X, Y: Longint); |
|
84 begin |
|
85 Modelview[3,0]:= X; |
|
86 Modelview[3,1]:= Y; |
|
87 end; |
|
88 |
|
89 procedure AddOffset(X, Y: GLfloat); // probably want to refactor this to use integers |
|
90 begin |
|
91 Modelview[3,0]:=Modelview[3,0] + Modelview[0,0]*X + Modelview[1,0]*Y; |
|
92 Modelview[3,1]:=Modelview[3,1] + Modelview[0,1]*X + Modelview[1,1]*Y; |
|
93 end; |
|
94 |
|
95 procedure SetScale(Scale: GLfloat); |
|
96 begin |
|
97 Modelview[0,0]:= Scale; |
|
98 Modelview[1,1]:= Scale; |
|
99 end; |
|
100 |
|
101 procedure AddScale(Scale: GLfloat); |
|
102 begin |
|
103 Modelview[0,0]:= Modelview[0,0]*Scale; Modelview[1,0]:= Modelview[1,0]*Scale; |
|
104 Modelview[0,1]:= Modelview[0,1]*Scale; Modelview[1,1]:= Modelview[1,1]*Scale; |
|
105 end; |
|
106 |
|
107 procedure AddScale(X, Y: GLfloat); |
|
108 begin |
|
109 Modelview[0,0]:= Modelview[0,0]*X; Modelview[1,0]:= Modelview[1,0]*Y; |
|
110 Modelview[0,1]:= Modelview[0,1]*X; Modelview[1,1]:= Modelview[1,1]*Y; |
|
111 end; |
|
112 |
|
113 |
|
114 procedure SetRotation(Angle, ZAxis: GLfloat); |
|
115 var s, c: Extended; |
|
116 begin |
|
117 SinCos(Angle*DegToRad, s, c); |
|
118 Modelview[0,0]:= c; Modelview[1,0]:=-s*ZAxis; |
|
119 Modelview[0,1]:= s*ZAxis; Modelview[1,1]:= c; |
|
120 end; |
|
121 |
|
122 procedure ResetRotation; |
|
123 begin |
|
124 Modelview[0,0]:= 1.0; Modelview[1,0]:=0.0; |
|
125 Modelview[0,1]:= 0.0; Modelview[1,1]:=1.0; |
|
126 end; |
|
127 |
|
128 procedure LoadIdentity(out Matrix: TMatrix4x4f); |
|
129 begin |
|
130 Matrix[0,0]:= 1.0; Matrix[1,0]:=0.0; Matrix[2,0]:=0.0; Matrix[3,0]:=0.0; |
|
131 Matrix[0,1]:= 0.0; Matrix[1,1]:=1.0; Matrix[2,1]:=0.0; Matrix[3,1]:=0.0; |
|
132 Matrix[0,2]:= 0.0; Matrix[1,2]:=0.0; Matrix[2,2]:=1.0; Matrix[3,2]:=0.0; |
|
133 Matrix[0,3]:= 0.0; Matrix[1,3]:=0.0; Matrix[2,3]:=0.0; Matrix[3,3]:=1.0; |
|
134 end; |
59 |
135 |
60 procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); |
136 procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); |
61 begin |
137 begin |
62 r.y:= r.y + Height * Position; |
138 r.y:= r.y + Height * Position; |
63 r.h:= Height; |
139 r.h:= Height; |
110 DrawTexture(X, Y, Texture, 1.0); |
186 DrawTexture(X, Y, Texture, 1.0); |
111 end; |
187 end; |
112 |
188 |
113 procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat); |
189 procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat); |
114 begin |
190 begin |
115 |
191 SetOffset(X, Y); |
116 glPushMatrix; |
192 ResetRotation; |
117 glTranslatef(X, Y, 0); |
193 SetScale(Scale); |
118 glScalef(Scale, Scale, 1); |
194 UpdateModelview; |
119 |
195 |
120 glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id); |
196 glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id); |
121 |
197 |
122 glVertexPointer(2, GL_FLOAT, 0, @Texture^.vb); |
198 glVertexPointer(2, GL_FLOAT, 0, @Texture^.vb); |
123 glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb); |
199 glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb); |
124 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb)); |
200 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb)); |
125 |
201 ResetModelview; |
126 glPopMatrix |
|
127 end; |
202 end; |
128 |
203 |
129 procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt); |
204 procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt); |
130 begin |
205 begin |
131 DrawTextureRotatedF(Texture, Scale, 0, 0, X, Y, Frame, Dir, w, h, 0) |
206 DrawTextureRotatedF(Texture, Scale, 0, 0, X, Y, Frame, Dir, w, h, 0) |
140 if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * cScaleFactor > cScreenWidth) then |
215 if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * cScaleFactor > cScreenWidth) then |
141 exit; |
216 exit; |
142 if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then |
217 if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then |
143 exit; |
218 exit; |
144 |
219 |
145 glPushMatrix; |
220 SetOffset(X, Y); |
146 glTranslatef(X, Y, 0); |
|
147 if Dir = 0 then Dir:= 1; |
221 if Dir = 0 then Dir:= 1; |
148 |
222 |
149 glRotatef(Angle, 0, 0, Dir); |
223 SetRotation(Angle, Dir); |
150 |
224 AddOffset(Dir*OffsetX, OffsetY); |
151 glTranslatef(Dir*OffsetX, OffsetY, 0); |
225 AddScale(Scale); |
152 glScalef(Scale, Scale, 1); |
226 UpdateModelview; |
153 |
227 |
154 // Any reason for this call? And why only in t direction, not s? |
228 // Any reason for this call? And why only in t direction, not s? |
155 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
229 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
156 |
230 |
157 hw:= w div (2 div Dir); |
231 hw:= w div (2 div Dir); |
178 |
252 |
179 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); |
253 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); |
180 glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]); |
254 glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]); |
181 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); |
255 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); |
182 |
256 |
183 glPopMatrix |
257 ResetModelview; |
184 end; |
258 end; |
185 |
259 |
186 procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real); |
260 procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real); |
187 begin |
261 begin |
188 DrawTextureRotated(SpritesData[Sprite].Texture, |
262 DrawTextureRotated(SpritesData[Sprite].Texture, |
191 X, Y, Dir, Angle) |
265 X, Y, Dir, Angle) |
192 end; |
266 end; |
193 |
267 |
194 procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); |
268 procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); |
195 begin |
269 begin |
196 glPushMatrix; |
270 SetOffset(X, Y); |
197 glTranslatef(X, Y, 0); |
|
198 |
|
199 if Dir < 0 then |
271 if Dir < 0 then |
200 glRotatef(Angle, 0, 0, -1) |
272 SetRotation(Angle, -1.0) |
201 else |
273 else |
202 glRotatef(Angle, 0, 0, 1); |
274 SetRotation(Angle, 1.0); |
203 if Dir < 0 then |
275 if Dir < 0 then |
204 glScalef(-1.0, 1.0, 1.0); |
276 AddScale(-1.0, 1.0); |
|
277 UpdateModelview; |
205 |
278 |
206 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame); |
279 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame); |
207 |
280 |
208 glPopMatrix |
281 ResetModelview; |
209 end; |
282 end; |
210 |
283 |
211 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real); |
284 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real); |
212 var VertexBuffer: array [0..3] of TVertex2f; |
285 var VertexBuffer: array [0..3] of TVertex2f; |
213 begin |
286 begin |
215 if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then |
288 if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then |
216 exit; |
289 exit; |
217 if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then |
290 if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then |
218 exit; |
291 exit; |
219 |
292 |
220 glPushMatrix; |
293 SetOffset(X, Y); |
221 glTranslatef(X, Y, 0); |
|
222 |
294 |
223 if Dir < 0 then |
295 if Dir < 0 then |
224 begin |
296 begin |
225 hw:= - hw; |
297 hw:= - hw; |
226 glRotatef(Angle, 0, 0, -1); |
298 SetRotation(Angle, -1.0); |
227 end |
299 end |
228 else |
300 else |
229 glRotatef(Angle, 0, 0, 1); |
301 SetRotation(Angle, 1.0); |
230 |
302 UpdateModelview; |
231 |
303 |
232 glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id); |
304 glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id); |
233 |
305 |
234 VertexBuffer[0].X:= -hw; |
306 VertexBuffer[0].X:= -hw; |
235 VertexBuffer[0].Y:= -hh; |
307 VertexBuffer[0].Y:= -hh; |
242 |
314 |
243 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); |
315 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); |
244 glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb); |
316 glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb); |
245 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); |
317 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); |
246 |
318 |
247 glPopMatrix |
319 ResetModelview; |
248 end; |
320 end; |
249 |
321 |
250 procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt); |
322 procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt); |
251 var row, col, numFramesFirstCol: LongInt; |
323 var row, col, numFramesFirstCol: LongInt; |
252 begin |
324 begin |
320 |
393 |
321 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); |
394 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); |
322 glDrawArrays(GL_LINES, 0, Length(VertexBuffer)); |
395 glDrawArrays(GL_LINES, 0, Length(VertexBuffer)); |
323 Tint($FF, $FF, $FF, $FF); |
396 Tint($FF, $FF, $FF, $FF); |
324 |
397 |
325 glPopMatrix; |
398 ResetModelview; |
326 |
399 |
327 glEnable(GL_TEXTURE_2D); |
400 glEnable(GL_TEXTURE_2D); |
328 glDisable(GL_LINE_SMOOTH); |
401 glDisable(GL_LINE_SMOOTH); |
329 end; |
402 end; |
330 |
403 |
331 procedure DrawFillRect(r: TSDL_Rect); |
404 procedure DrawFillRect(r: TSDL_Rect); |
332 var VertexBuffer: array [0..3] of TVertex2f; |
405 var VertexBuffer: array [0..3] of TVertex2f; |
333 begin |
406 begin |
|
407 SetOffset(0, 0); |
|
408 ResetRotation; |
|
409 UpdateModelview; |
|
410 |
334 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs) |
411 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs) |
335 if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then |
412 if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then |
336 exit; |
413 exit; |
337 if (abs(r.y) > r.h) and ((abs(r.y + r.h / 2 - (0.5 * cScreenHeight)) - r.h / 2) * cScaleFactor > cScreenHeight) then |
414 if (abs(r.y) > r.h) and ((abs(r.y + r.h / 2 - (0.5 * cScreenHeight)) - r.h / 2) * cScaleFactor > cScreenHeight) then |
338 exit; |
415 exit; |
352 |
429 |
353 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); |
430 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); |
354 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); |
431 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); |
355 |
432 |
356 Tint($FF, $FF, $FF, $FF); |
433 Tint($FF, $FF, $FF, $FF); |
357 glEnable(GL_TEXTURE_2D) |
434 glEnable(GL_TEXTURE_2D); |
|
435 |
|
436 ResetModelview; |
358 end; |
437 end; |
359 |
438 |
360 procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte); |
439 procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte); |
361 begin |
440 begin |
362 Tint(r, g, b, a); |
441 Tint(r, g, b, a); |
373 CircleVertex[i].X := X + Radius*cos(i*pi/30); |
452 CircleVertex[i].X := X + Radius*cos(i*pi/30); |
374 CircleVertex[i].Y := Y + Radius*sin(i*pi/30); |
453 CircleVertex[i].Y := Y + Radius*sin(i*pi/30); |
375 end; |
454 end; |
376 glDisable(GL_TEXTURE_2D); |
455 glDisable(GL_TEXTURE_2D); |
377 glEnable(GL_LINE_SMOOTH); |
456 glEnable(GL_LINE_SMOOTH); |
378 glPushMatrix; |
457 SetOffset(0, 0); |
|
458 ResetRotation; |
|
459 UpdateModelview; |
379 glLineWidth(Width); |
460 glLineWidth(Width); |
380 glVertexPointer(2, GL_FLOAT, 0, @CircleVertex[0]); |
461 glVertexPointer(2, GL_FLOAT, 0, @CircleVertex[0]); |
381 glDrawArrays(GL_LINE_LOOP, 0, 60); |
462 glDrawArrays(GL_LINE_LOOP, 0, 60); |
382 glPopMatrix; |
|
383 glEnable(GL_TEXTURE_2D); |
463 glEnable(GL_TEXTURE_2D); |
384 glDisable(GL_LINE_SMOOTH); |
464 glDisable(GL_LINE_SMOOTH); |
|
465 ResetModelview; |
385 end; |
466 end; |
386 |
467 |
387 |
468 |
388 procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real); |
469 procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real); |
389 const VertexBuffers: array[0..1] of TVertexRect = ( |
470 const VertexBuffers: array[0..1] of TVertexRect = ( |
408 r.y:=Pos * 32; |
489 r.y:=Pos * 32; |
409 r.w:=32; |
490 r.w:=32; |
410 r.h:=32; |
491 r.h:=32; |
411 ComputeTexcoords(HHTexture, @r, @TextureBuffer); |
492 ComputeTexcoords(HHTexture, @r, @TextureBuffer); |
412 |
493 |
413 glPushMatrix(); |
494 SetOffset(X, Y); |
414 glTranslatef(X, Y, 0); |
495 SetRotation(Angle, 1.0); |
415 glRotatef(Angle, 0, 0, 1); |
496 UpdateModelview; |
416 |
497 |
417 glBindTexture(GL_TEXTURE_2D, HHTexture^.atlas^.id); |
498 glBindTexture(GL_TEXTURE_2D, HHTexture^.atlas^.id); |
418 if Dir = -1 then |
499 if Dir = -1 then |
419 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffers[1][0]) |
500 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffers[1][0]) |
420 else |
501 else |
421 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffers[0][0]); |
502 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffers[0][0]); |
422 glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]); |
503 glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]); |
423 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
504 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
424 |
505 |
425 glPopMatrix |
506 ResetModelview; |
426 end; |
507 end; |
427 |
508 |
428 procedure DrawScreenWidget(widget: POnScreenWidget); |
509 procedure DrawScreenWidget(widget: POnScreenWidget); |
429 {$IFDEF USE_TOUCH_INTERFACE} |
510 {$IFDEF USE_TOUCH_INTERFACE} |
430 var alpha: byte = $FF; |
511 var alpha: byte = $FF; |