fpc/packages/libndsfpc/examples/gl2d/2Dplus3D/vbuffer.pas
Legolas 96cab58ab4 * Fixed typo
git-svn-id: trunk@19949 -
2012-01-02 13:13:34 +00:00

496 lines
12 KiB
ObjectPascal

(*
Space Impakto DS
relminator
Http://Rel.Phatcode.Net
TVertexbuffer class
*)
unit VBuffer;
{$mode objfpc}
{$H+}
interface
uses
ctypes, nds9, math;
const
PI = 3.141593;
TWOPI: cfloat = PI * 2;
type
TVector3f32 = packed record
x: cint32;
y: cint32;
z: cint32;
end;
PVector3f32 = ^TVector3f32;
TRGBf32 = packed record
r: cint32;
g: cint32;
b: cint32;
end;
PRGBf32 = ^TRGBf32;
TTexcoordf32 = packed record
u: cint32;
v: cint32;
end;
PTexcoordf32 =^TTexcoordf32;
TPolygon = packed record
v1: cuint32;
v2: cuint32;
v3: cuint32;
end;
PPolygon = ^TPolygon;
// vertex buffer object. LOL
TVertexbuffer = class
public
i_max_poly: cint;
i_max_vertex: cint;
i_primitive_type: cint;
i_texture_ID: cint;
ips_vertex: array of TVector3f32;
ips_texture: array of TTexcoordf32;
ips_color: array of TRGBf32;
ps_poly: array of TPolygon;
constructor Create;
destructor Destroy;
procedure render(text_off_u, text_off_v: cint32; colorize: boolean);
//procedure render_lines(r, g, b: cuint8);
function load_texture(texture_gfx: pcuint8): cint;
end;
PVertexBuffer = ^TVertexBuffer;
function init_grid( rings, bands: cint;
width, height: cfloat;
uscale, vscale: cint): PVertexBuffer;
function init_super_shape(rings, bands: cint;
radius: cfloat;
uscale, vscale: cint;
a, b, m, n1, n2, n3: cfloat): PVertexBuffer;
function init_ascaris(rings, bands: cint;
radius, center_offset: cfloat;
uscale, vscale: cint): PVertexBuffer;
implementation
constructor TVertexBuffer.Create();
begin
SetLength(ips_vertex, 0);
SetLength(ips_texture, 0);
SetLength(ips_color, 0);
SetLength(ps_poly, 0);
i_max_poly := 0;
i_primitive_type := 0;
i_texture_ID := 0;
end;
destructor TVertexBuffer.Destroy();
begin
if Length(ips_vertex) > 0 then
SetLength(ips_vertex, 0);
if Length(ps_poly) > 0 then
SetLength(ps_poly, 0);
i_max_poly := 0;
i_primitive_type := 0;
i_texture_ID := 0;
if Length(ips_texture) > 0 then
SetLength(ips_texture, 0);
if Length(ips_color) > 0 then
SetLength(ips_color, 0);
end;
procedure TVertexbuffer.render(text_off_u, text_off_v: cint32; colorize: boolean);
var
i: integer;
i1,i2,i3: integer;
begin
glEnable(GL_TEXTURE_2D);
glBindTexture(0, i_texture_ID);
if (colorize) then
begin
glBegin (GL_TRIANGLES);
//glNormal(NORMAL_PACK(0,inttov10(-1),0));
for i := 0 to i_max_poly - 1 do
begin
i1 := ps_poly[i].v1;
i2 := ps_poly[i].v2;
i3 := ps_poly[i].v3;
glColor3b(ips_color[i1].r, ips_color[i1].g, ips_color[i1].b);
glTexCoord2f32(ips_texture[i1].u + text_off_u, ips_texture[i1].v + text_off_v);
glVertex3v16(ips_vertex[i1].x, ips_vertex[i1].y, ips_vertex[i1].z);
glColor3b(ips_color[i2].r, ips_color[i2].g, ips_color[i2].b);
glTexCoord2f32(ips_texture[i2].u + text_off_u, ips_texture[i2].v + text_off_v);
glVertex3v16(ips_vertex[i2].x, ips_vertex[i2].y, ips_vertex[i2].z);
glColor3b(ips_color[i3].r, ips_color[i3].g, ips_color[i3].b);
glTexCoord2f32(ips_texture[i3].u + text_off_u, ips_texture[i3].v + text_off_v);
glVertex3v16(ips_vertex[i3].x, ips_vertex[i3].y, ips_vertex[i3].z);
end;
glEnd();
end else
begin
glBegin (GL_TRIANGLES);
//glNormal(NORMAL_PACK(0,inttov10(-1),0));
for i := 0 to i_max_poly - 1 do
begin
i1 := ps_poly[i].v1;
i2 := ps_poly[i].v2;
i3 := ps_poly[i].v3;
glTexCoord2f32(ips_texture[i1].u +text_off_u,ips_texture[i1].v +text_off_v);
glVertex3v16 (ips_vertex[i1].x,ips_vertex[i1].y,ips_vertex[i1].z);
glTexCoord2f32 (ips_texture[i2].u + text_off_u,ips_texture[i2].v +text_off_v);
glVertex3v16 (ips_vertex[i2].x,ips_vertex[i2].y,ips_vertex[i2].z);
glTexCoord2f32 (ips_texture[i3].u + text_off_u,ips_texture[i3].v +text_off_v);
glVertex3v16 (ips_vertex[i3].x,ips_vertex[i3].y,ips_vertex[i3].z);
end;
glEnd();
end;
end;
function Tvertexbuffer.load_texture(texture_gfx: pcuint8): cint;
begin
if (texture_gfx^) = 0 then
result := 1
else
begin
glGenTextures(1, @i_texture_ID);
glBindTexture(0, i_texture_ID);
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);
result := 0;
end;
end;
// special functions
function init_grid(rings, bands: cint; width, height: cfloat; uscale, vscale: cint): PVertexBuffer;
var
vb: PVertexBuffer;
max_point: cint;
ivertex: array of TVector3f32;
itexture: array of TTexcoordf32;
icolor: array of TRGBf32;
poly: array of TPolygon;
s, u, slice, maxvert: cint;
i: cint;
ii, jj: integer;
half_width, half_height, a1, a2: cfloat;
k: cint;
x, y, z: cfloat;
_u, _v: cfloat;
begin
new(vb);
vb^ := TVertexBuffer.Create();
max_point := (rings) * (bands); //+1 for last band duplicate
SetLength(ivertex, max_point);
SetLength(itexture, max_point); //
SetLength(icolor, max_point);
SetLength(poly, max_point * 2); //
vb^.ips_vertex := ivertex;
vb^.ips_texture := itexture;
vb^.ips_color := icolor;
vb^.ps_poly := poly;
vb^.i_max_vertex := max_point;
vb^.i_max_poly := max_point * 2;
vb^.i_primitive_type := GL_TRIANGLES;
maxvert := max_point;
i := 0;
for s := 0 to rings - 1 do
begin
slice := s * bands;
for u := 0 to bands - 1 do //duplicate texture ( not bands - 1)
begin
poly[i].v1 := (u + bands + 1 + (slice)) mod maxvert;
poly[i].v2 := (u + bands + (slice)) mod maxvert;
poly[i].v3 := (u + (slice)) mod maxvert;
poly[i+1].v1 := (u + (slice)) mod maxvert;
poly[i+1].v2 := (u + 1 + (slice)) mod maxvert;
poly[i+1].v3 := (u + bands + 1 + (slice)) mod maxvert;
inc(i, 2);
end;
end;
half_width := width / 2;
half_height := height / 2;
a1 := 2 * width / rings;
a2 := 2 * height / bands;
k := 0;
for ii := 0 to rings - 1 do
begin
for jj := 0 to bands - 1 do
begin
x := -half_width + (ii * a1);
y := 0;
z := -half_height + (jj * a2);;
ivertex[k].x := floattov16(x);
ivertex[k].y := floattov16(y);
ivertex[k].z := floattov16(z);
icolor[k].r := (1 - (jj * 4 div bands)) * 255;
icolor[k].g := (1 - (jj * 4 div bands)) * 255;
icolor[k].b := (1 - (jj * 4 div bands)) * 255;
_u := (ii / rings ) * uscale;
_v := (jj / bands ) * vscale;
itexture[k].u := floattof32(_u);
itexture[k].v := floattof32(_v);
inc(k);
end;
end;
result := vb;
end;
function init_super_shape (rings, bands: cint; radius: cfloat; uscale, vscale: cint;
a, b, m, n1, n2, n3: cfloat): PVertexBuffer;
var
vb: PVertexBuffer;
max_point: cint;
ivertex: array of TVector3f32;
itexture: array of TTexcoordf32;
icolor: array of Trgbf32;
poly: array of Tpolygon;
s, u, slice, maxvert: cint;
i: cint;
phi, theta: cfloat;
r1, r2, a1, a2: cfloat;
Tpi_d: cfloat;
Ppi_d: cfloat;
k: cint;
ii, jj: integer;
x, y, z: cfloat;
_u, _v: cint;
begin
new(vb);
vb^ := TVertexBuffer.Create();
max_point := rings * (bands + 1); //+1 for last band duplicate
SetLength(ivertex, max_point);
SetLength(itexture, max_point);
SetLength(icolor, max_point);
SetLength(poly, max_point * 2);
vb^.ips_vertex := ivertex;
vb^.ips_texture := itexture;
vb^.ips_color := icolor;
vb^.ps_poly := poly;
vb^.i_max_vertex := max_point;
vb^.i_max_poly := max_point * 2;
vb^.i_primitive_type := GL_TRIANGLES;
//lathing
maxvert := max_point;
i := 0;
for s := 0 to rings - 1 do
begin
slice := s * bands;
for u := 0 to bands - 1 do
begin
poly[i].v1:=(u+bands+1+(slice)) mod maxvert;
poly[i].v2:=(u+bands+(slice)) mod maxvert;
poly[i].v3:=(u+(slice)) mod maxvert;
poly[i+1].v1:=(u+(slice)) mod maxvert;
poly[i+1].v2:=(u+1+(slice)) mod maxvert;
poly[i+1].v3:=(u+bands+1+(slice)) mod maxvert;
inc(i, 2);
end;
end;
Tpi_d := TWOPI / bands;
Ppi_d := PI / rings;
phi := -PI / 2;
k := 0;
for ii := 0 to rings - 1 do
begin
a1 := power(abs(cos(m * phi / 4) / a), n2);
a2 := power(abs(sin(m * phi / 4) / b), n3);
r2 := power(a1 + a2, -1 / n1) ;
r2 := r2 * radius;
phi := phi + Ppi_d;
theta := -PI;
for jj := 0 to bands do
begin
a1 := power(abs(cos(m * theta / 4) / a), n2);
a2 := power(abs(sin(m * theta / 4) / b), n3);
r1 := power(a1 + a2, -1 / n1) ;
r1 := r1 * radius;
x := r1 * cos(theta) * r2 * cos(phi);
y := r1 * sin(theta) * r2 * cos(phi);
z := r2 * sin(phi);
theta := theta + Tpi_d;
ivertex[k].x := floattov16 (x);
ivertex[k].y := floattov16 (y);
ivertex[k].z := floattov16 (z);
icolor[k].r := (1 - (ii * 4 div rings)) * 255;
icolor[k].g := (1 - (ii * 4 div rings)) * 255;
icolor[k].b := (1 - (ii * 4 div rings)) * 255;
_u := (ii div rings ) * uscale;
_v := (jj div bands ) * vscale;
itexture[k].u := floattof32(_u);
itexture[k].v := floattof32(_v);
inc(k);
end;
end;
result := vb;
end;
// initialize out tunnel and
// store float values to f32 classes
function init_ascaris(rings, bands: cint; radius, center_offset: cfloat; uscale, vscale: cint): PVertexBuffer;
var
vb: PVertexBuffer;
max_point: cint;
ivertex: array of TVector3f32;
itexture: array of Ttexcoordf32;
icolor: array of Trgbf32;
poly: array of TPolygon;
s, u, slice, maxvert: cint;
i: cint;
ii, jj: integer;
half_width, half_height, a1, a2: cfloat;
k: cint;
x, y, z: cfloat;
_u, _v: cfloat;
xc, yc, zc: cfloat;
begin
new(vb);
vb^ := TVertexBuffer.Create();
max_point := (rings) * (bands + 1); //+1 for last band duplicate
setlength(ivertex, max_point);
setlength(itexture, max_point);
setlength(icolor, max_point);
setlength(poly, max_point * 2);
vb^.ips_vertex := ivertex;
vb^.ips_texture := itexture;
vb^.ips_color := icolor;
vb^.ps_poly := poly;
vb^.i_max_vertex := max_point;
vb^.i_max_poly := max_point * 2;
vb^.i_primitive_type := GL_TRIANGLES;
//lathing
maxvert := max_point;
i := 0;
for s := 0 to (rings - 1) do
begin
slice := s * bands;
for u := 0 to bands do //duplicate texture ( not bands - 1)
begin
poly[i].v1:=(u+bands+1+(slice)) mod maxvert;
poly[i].v2:=(u+bands+(slice)) mod maxvert;
poly[i].v3:=(u+(slice)) mod maxvert;
poly[i+1].v1:=(u+(slice)) mod maxvert;
poly[i+1].v2:=(u+1+(slice)) mod maxvert;
poly[i+1].v3:=(u+bands+1+(slice)) mod maxvert;
inc(i, 2);
end;
end;
k := 0;
for ii := 0 to rings - 1 do
begin
zc := ii - (ii/20);
xc := cos(TWOPI * zc / rings)* center_offset;
yc := sin(TWOPI * zc / rings)* center_offset;
for jj := 0 to bands do
begin
x := xc + cos(jj * TWOPI / bands ) * radius;
y := yc + sin(jj * TWOPI / bands ) * radius;
z := 0-(ii*2);
ivertex[k].x := floattov16 (x);
ivertex[k].y := floattov16 (y);
ivertex[k].z := floattov16 (z);
icolor[k].r := (1 - (ii*4 div rings)) * 255;
icolor[k].g := (1 - (ii*4 div rings)) * 255;
icolor[k].b := (1 - (ii*4 div rings)) * 255;
_u := (ii / rings ) * uscale;
_v := (jj / bands ) * vscale;
itexture[k].u := floattof32(_u);
itexture[k].v := floattof32(_v);
inc(k);
end;
end;
result := vb;
end;
end.