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