1 (*
2 Space Impakto DS
3 relminator
4 Http://Rel.Phatcode.Net
5
6 TVertexbuffer class
7 *)
8
9 unit VBuffer;
10
11 {$mode objfpc}
12 {$H+}
13
14 interface
15
16 uses
17 ctypes, nds9, math;
18
19
20 const
21 PI = 3.141593;
22 TWOPI: cfloat = PI * 2;
23
24 type
25 TVector3f32 = packed record
26 x: cint32;
27 y: cint32;
28 z: cint32;
29 end;
30 PVector3f32 = ^TVector3f32;
31
32
33 TRGBf32 = packed record
34 r: cint32;
35 g: cint32;
36 b: cint32;
37 end;
38 PRGBf32 = ^TRGBf32;
39
40 TTexcoordf32 = packed record
41 u: cint32;
42 v: cint32;
43 end;
44 PTexcoordf32 =^TTexcoordf32;
45
46 TPolygon = packed record
47 v1: cuint32;
48 v2: cuint32;
49 v3: cuint32;
50 end;
51 PPolygon = ^TPolygon;
52
53 // vertex buffer object. LOL
54 TVertexbuffer = class
55 public
56 i_max_poly: cint;
57 i_max_vertex: cint;
58 i_primitive_type: cint;
59 i_texture_ID: cint;
60 ips_vertex: array of TVector3f32;
61 ips_texture: array of TTexcoordf32;
62 ips_color: array of TRGBf32;
63 ps_poly: array of TPolygon;
64 constructor Create;
65 destructor Destroy;
66 procedure render(text_off_u, text_off_v: cint32; colorize: boolean);
67 //procedure render_lines(r, g, b: cuint8);
load_texturenull68 function load_texture(texture_gfx: pcuint8): cint;
69 end;
70 PVertexBuffer = ^TVertexBuffer;
71
72
init_gridnull73 function init_grid( rings, bands: cint;
74 width, height: cfloat;
75 uscale, vscale: cint): PVertexBuffer;
init_super_shapenull76 function init_super_shape(rings, bands: cint;
77 radius: cfloat;
78 uscale, vscale: cint;
79 a, b, m, n1, n2, n3: cfloat): PVertexBuffer;
init_ascarisnull80 function init_ascaris(rings, bands: cint;
81 radius, center_offset: cfloat;
82 uscale, vscale: cint): PVertexBuffer;
83
84
85 implementation
86
87 constructor TVertexBuffer.Create();
88 begin
89 SetLength(ips_vertex, 0);
90 SetLength(ips_texture, 0);
91 SetLength(ips_color, 0);
92 SetLength(ps_poly, 0);
93
94 i_max_poly := 0;
95 i_primitive_type := 0;
96 i_texture_ID := 0;
97 end;
98
99 destructor TVertexBuffer.Destroy();
100 begin
101
102 if Length(ips_vertex) > 0 then
103 SetLength(ips_vertex, 0);
104
105 if Length(ps_poly) > 0 then
106 SetLength(ps_poly, 0);
107
108 i_max_poly := 0;
109 i_primitive_type := 0;
110 i_texture_ID := 0;
111
112 if Length(ips_texture) > 0 then
113 SetLength(ips_texture, 0);
114
115 if Length(ips_color) > 0 then
116 SetLength(ips_color, 0);
117
118 end;
119
120 procedure TVertexbuffer.render(text_off_u, text_off_v: cint32; colorize: boolean);
121 var
122 i: integer;
123 i1,i2,i3: integer;
124 begin
125 glEnable(GL_TEXTURE_2D);
126 glBindTexture(0, i_texture_ID);
127 if (colorize) then
128 begin
129 glBegin (GL_TRIANGLES);
130 //glNormal(NORMAL_PACK(0,inttov10(-1),0));
131 for i := 0 to i_max_poly - 1 do
132 begin
133 i1 := ps_poly[i].v1;
134 i2 := ps_poly[i].v2;
135 i3 := ps_poly[i].v3;
136
137 glColor3b(ips_color[i1].r, ips_color[i1].g, ips_color[i1].b);
138 glTexCoord2f32(ips_texture[i1].u + text_off_u, ips_texture[i1].v + text_off_v);
139 glVertex3v16(ips_vertex[i1].x, ips_vertex[i1].y, ips_vertex[i1].z);
140
141 glColor3b(ips_color[i2].r, ips_color[i2].g, ips_color[i2].b);
142 glTexCoord2f32(ips_texture[i2].u + text_off_u, ips_texture[i2].v + text_off_v);
143 glVertex3v16(ips_vertex[i2].x, ips_vertex[i2].y, ips_vertex[i2].z);
144
145 glColor3b(ips_color[i3].r, ips_color[i3].g, ips_color[i3].b);
146 glTexCoord2f32(ips_texture[i3].u + text_off_u, ips_texture[i3].v + text_off_v);
147 glVertex3v16(ips_vertex[i3].x, ips_vertex[i3].y, ips_vertex[i3].z);
148
149 end;
150 glEnd();
151 end else
152 begin
153 glBegin (GL_TRIANGLES);
154 //glNormal(NORMAL_PACK(0,inttov10(-1),0));
155 for i := 0 to i_max_poly - 1 do
156 begin
157 i1 := ps_poly[i].v1;
158 i2 := ps_poly[i].v2;
159 i3 := ps_poly[i].v3;
160
161 glTexCoord2f32(ips_texture[i1].u +text_off_u,ips_texture[i1].v +text_off_v);
162 glVertex3v16 (ips_vertex[i1].x,ips_vertex[i1].y,ips_vertex[i1].z);
163
164 glTexCoord2f32 (ips_texture[i2].u + text_off_u,ips_texture[i2].v +text_off_v);
165 glVertex3v16 (ips_vertex[i2].x,ips_vertex[i2].y,ips_vertex[i2].z);
166
167 glTexCoord2f32 (ips_texture[i3].u + text_off_u,ips_texture[i3].v +text_off_v);
168 glVertex3v16 (ips_vertex[i3].x,ips_vertex[i3].y,ips_vertex[i3].z);
169
170 end;
171 glEnd();
172 end;
173 end;
174
175
load_texturenull176 function Tvertexbuffer.load_texture(texture_gfx: pcuint8): cint;
177 begin
178 if (texture_gfx^) = 0 then
179 result := 1
180 else
181 begin
182 glGenTextures(1, @i_texture_ID);
183 glBindTexture(0, i_texture_ID);
184 glTexImage2D( 0, 0, GL_RGB, TEXTURE_SIZE_128 , TEXTURE_SIZE_128, 0, GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T or TEXGEN_TEXCOORD, texture_gfx);
185 result := 0;
186 end;
187 end;
188
189 // special functions
init_gridnull190 function init_grid(rings, bands: cint; width, height: cfloat; uscale, vscale: cint): PVertexBuffer;
191 var
192 vb: PVertexBuffer;
193 max_point: cint;
194 ivertex: array of TVector3f32;
195 itexture: array of TTexcoordf32;
196 icolor: array of TRGBf32;
197 poly: array of TPolygon;
198 s, u, slice, maxvert: cint;
199 i: cint;
200 ii, jj: integer;
201 half_width, half_height, a1, a2: cfloat;
202 k: cint;
203 x, y, z: cfloat;
204 _u, _v: cfloat;
205 begin
206 new(vb);
207 vb^ := TVertexBuffer.Create();
208
209 max_point := (rings) * (bands); //+1 for last band duplicate
210
211 SetLength(ivertex, max_point);
212 SetLength(itexture, max_point); //
213 SetLength(icolor, max_point);
214 SetLength(poly, max_point * 2); //
215
216 vb^.ips_vertex := ivertex;
217 vb^.ips_texture := itexture;
218 vb^.ips_color := icolor;
219 vb^.ps_poly := poly;
220
221 vb^.i_max_vertex := max_point;
222 vb^.i_max_poly := max_point * 2;
223 vb^.i_primitive_type := GL_TRIANGLES;
224
225 maxvert := max_point;
226 i := 0;
227 for s := 0 to rings - 1 do
228 begin
229 slice := s * bands;
230 for u := 0 to bands - 1 do //duplicate texture ( not bands - 1)
231 begin
232 poly[i].v1 := (u + bands + 1 + (slice)) mod maxvert;
233 poly[i].v2 := (u + bands + (slice)) mod maxvert;
234 poly[i].v3 := (u + (slice)) mod maxvert;
235 poly[i+1].v1 := (u + (slice)) mod maxvert;
236 poly[i+1].v2 := (u + 1 + (slice)) mod maxvert;
237 poly[i+1].v3 := (u + bands + 1 + (slice)) mod maxvert;
238 inc(i, 2);
239 end;
240 end;
241
242
243 half_width := width / 2;
244 half_height := height / 2;
245
246
247 a1 := 2 * width / rings;
248 a2 := 2 * height / bands;
249 k := 0;
250
251
252 for ii := 0 to rings - 1 do
253 begin
254 for jj := 0 to bands - 1 do
255 begin
256 x := -half_width + (ii * a1);
257 y := 0;
258 z := -half_height + (jj * a2);;
259
260 ivertex[k].x := floattov16(x);
261 ivertex[k].y := floattov16(y);
262 ivertex[k].z := floattov16(z);
263
264 icolor[k].r := (1 - (jj * 4 div bands)) * 255;
265 icolor[k].g := (1 - (jj * 4 div bands)) * 255;
266 icolor[k].b := (1 - (jj * 4 div bands)) * 255;
267
268 _u := (ii / rings ) * uscale;
269 _v := (jj / bands ) * vscale;
270
271
272 itexture[k].u := floattof32(_u);
273 itexture[k].v := floattof32(_v);
274
275 inc(k);
276
277 end;
278 end;
279
280 result := vb;
281
282 end;
283
init_super_shapenull284 function init_super_shape (rings, bands: cint; radius: cfloat; uscale, vscale: cint;
285 a, b, m, n1, n2, n3: cfloat): PVertexBuffer;
286 var
287 vb: PVertexBuffer;
288 max_point: cint;
289 ivertex: array of TVector3f32;
290 itexture: array of TTexcoordf32;
291 icolor: array of Trgbf32;
292 poly: array of Tpolygon;
293 s, u, slice, maxvert: cint;
294 i: cint;
295
296 phi, theta: cfloat;
297 r1, r2, a1, a2: cfloat;
298
299 Tpi_d: cfloat;
300 Ppi_d: cfloat;
301 k: cint;
302
303 ii, jj: integer;
304 x, y, z: cfloat;
305 _u, _v: cint;
306
307 begin
308 new(vb);
309 vb^ := TVertexBuffer.Create();
310
311 max_point := rings * (bands + 1); //+1 for last band duplicate
312 SetLength(ivertex, max_point);
313 SetLength(itexture, max_point);
314 SetLength(icolor, max_point);
315 SetLength(poly, max_point * 2);
316
317 vb^.ips_vertex := ivertex;
318 vb^.ips_texture := itexture;
319 vb^.ips_color := icolor;
320 vb^.ps_poly := poly;
321
322 vb^.i_max_vertex := max_point;
323 vb^.i_max_poly := max_point * 2;
324 vb^.i_primitive_type := GL_TRIANGLES;
325
326 //lathing
327 maxvert := max_point;
328 i := 0;
329 for s := 0 to rings - 1 do
330 begin
331 slice := s * bands;
332 for u := 0 to bands - 1 do
333 begin
334 poly[i].v1:=(u+bands+1+(slice)) mod maxvert;
335 poly[i].v2:=(u+bands+(slice)) mod maxvert;
336 poly[i].v3:=(u+(slice)) mod maxvert;
337 poly[i+1].v1:=(u+(slice)) mod maxvert;
338 poly[i+1].v2:=(u+1+(slice)) mod maxvert;
339 poly[i+1].v3:=(u+bands+1+(slice)) mod maxvert;
340 inc(i, 2);
341 end;
342 end;
343
344
345
346 Tpi_d := TWOPI / bands;
347 Ppi_d := PI / rings;
348
349 phi := -PI / 2;
350
351 k := 0;
352
353 for ii := 0 to rings - 1 do
354 begin
355
356 a1 := power(abs(cos(m * phi / 4) / a), n2);
357 a2 := power(abs(sin(m * phi / 4) / b), n3);
358 r2 := power(a1 + a2, -1 / n1) ;
359 r2 := r2 * radius;
360
361 phi := phi + Ppi_d;
362
363 theta := -PI;
364
365 for jj := 0 to bands do
366 begin
367
368 a1 := power(abs(cos(m * theta / 4) / a), n2);
369 a2 := power(abs(sin(m * theta / 4) / b), n3);
370 r1 := power(a1 + a2, -1 / n1) ;
371 r1 := r1 * radius;
372
373
374 x := r1 * cos(theta) * r2 * cos(phi);
375 y := r1 * sin(theta) * r2 * cos(phi);
376 z := r2 * sin(phi);
377
378 theta := theta + Tpi_d;
379
380 ivertex[k].x := floattov16 (x);
381 ivertex[k].y := floattov16 (y);
382 ivertex[k].z := floattov16 (z);
383
384 icolor[k].r := (1 - (ii * 4 div rings)) * 255;
385 icolor[k].g := (1 - (ii * 4 div rings)) * 255;
386 icolor[k].b := (1 - (ii * 4 div rings)) * 255;
387
388 _u := (ii div rings ) * uscale;
389 _v := (jj div bands ) * vscale;
390
391
392 itexture[k].u := floattof32(_u);
393 itexture[k].v := floattof32(_v);
394
395 inc(k);
396
397 end;
398 end;
399
400 result := vb;
401 end;
402
403 // initialize out tunnel and
404 // store float values to f32 classes
init_ascarisnull405 function init_ascaris(rings, bands: cint; radius, center_offset: cfloat; uscale, vscale: cint): PVertexBuffer;
406 var
407 vb: PVertexBuffer;
408 max_point: cint;
409 ivertex: array of TVector3f32;
410 itexture: array of Ttexcoordf32;
411 icolor: array of Trgbf32;
412 poly: array of TPolygon;
413 s, u, slice, maxvert: cint;
414 i: cint;
415 ii, jj: integer;
416 half_width, half_height, a1, a2: cfloat;
417 k: cint;
418 x, y, z: cfloat;
419 _u, _v: cfloat;
420 xc, yc, zc: cfloat;
421
422 begin
423 new(vb);
424 vb^ := TVertexBuffer.Create();
425
426 max_point := (rings) * (bands + 1); //+1 for last band duplicate
427 setlength(ivertex, max_point);
428 setlength(itexture, max_point);
429 setlength(icolor, max_point);
430 setlength(poly, max_point * 2);
431
432 vb^.ips_vertex := ivertex;
433 vb^.ips_texture := itexture;
434 vb^.ips_color := icolor;
435 vb^.ps_poly := poly;
436
437 vb^.i_max_vertex := max_point;
438 vb^.i_max_poly := max_point * 2;
439 vb^.i_primitive_type := GL_TRIANGLES;
440
441
442 //lathing
443 maxvert := max_point;
444 i := 0;
445 for s := 0 to (rings - 1) do
446 begin
447 slice := s * bands;
448 for u := 0 to bands do //duplicate texture ( not bands - 1)
449 begin
450 poly[i].v1:=(u+bands+1+(slice)) mod maxvert;
451 poly[i].v2:=(u+bands+(slice)) mod maxvert;
452 poly[i].v3:=(u+(slice)) mod maxvert;
453 poly[i+1].v1:=(u+(slice)) mod maxvert;
454 poly[i+1].v2:=(u+1+(slice)) mod maxvert;
455 poly[i+1].v3:=(u+bands+1+(slice)) mod maxvert;
456 inc(i, 2);
457 end;
458 end;
459
460
461 k := 0;
462 for ii := 0 to rings - 1 do
463 begin
464 zc := ii - (ii/20);
465 xc := cos(TWOPI * zc / rings)* center_offset;
466 yc := sin(TWOPI * zc / rings)* center_offset;
467 for jj := 0 to bands do
468 begin
469
470 x := xc + cos(jj * TWOPI / bands ) * radius;
471 y := yc + sin(jj * TWOPI / bands ) * radius;
472 z := 0-(ii*2);
473
474 ivertex[k].x := floattov16 (x);
475 ivertex[k].y := floattov16 (y);
476 ivertex[k].z := floattov16 (z);
477
478 icolor[k].r := (1 - (ii*4 div rings)) * 255;
479 icolor[k].g := (1 - (ii*4 div rings)) * 255;
480 icolor[k].b := (1 - (ii*4 div rings)) * 255;
481
482 _u := (ii / rings ) * uscale;
483 _v := (jj / bands ) * vscale;
484
485 itexture[k].u := floattof32(_u);
486 itexture[k].v := floattof32(_v);
487
488 inc(k);
489 end;
490 end;
491
492 result := vb;
493 end;
494
495 end.
496