Code: Select all
type gfx_buffer
wwidth as long
height as long
pitch as long
pixels as ulong pointer
depth as single pointer
normal_data as ubyte ptr
normal as single pointer
vp_l as long
vp_r as long
vp_t as long
vp_b as long
u_mask as long
v_mask as long
v_shift as long
wwidth_f as single
height_f as single
ripmap_u as gfx_buffer pointer
ripmap_v as gfx_buffer pointer
flags as ulong
declare constructor(byval as long,byval as long,byval as long=0)
declare destructor()
end type
type vertex
as single x,y,z,pad0
as single nx,ny,nz,pad1
as single tx,ty,tz,pad2
as single bx,by,bz,pad3
as single rx,ry,rz,pad4
as single sx,sy,sz,pad5
as single b,g,r,a
as single sb,sg,sr,sa
as single u0,v0,u1,v1
as single su0,sv0,su1,sv1
as single scx,scy,scz,scw
as single slx,sly,slz,slw
as vertex ptr next_vertex
as any ptr vertex_data
end type
type vertex_data
as ubyte dat(0 to sizeof(vertex)+15)
end type
type triangle
as vertex ptr v0,v1,v2
as single nx,ny,nz,nw
as single tx,ty,tz,tw
as single bx,by,bz,bw
texture as gfx_buffer ptr
n_map as gfx_buffer ptr
as ulong argb
as triangle ptr next_triangle
end type
type model
as triangle ptr first_triangle
as vertex ptr first_vertex
as model ptr next_model
end type
type entity
as ubyte matrix_data(80+15)
as single ptr m
as model ptr model
as entity ptr next_entity
end type
type world
as entity ptr camera
as entity ptr light
as entity ptr first_entity
as model ptr first_model
end type
function create_world()as world ptr
return new world
end function
function create_camera(byval world as world ptr)as entity ptr
world->camera=new entity
world->camera->m=cast(single ptr,(cast(ulong,@world->camera->matrix_data(0))+15)and &hfffffff0)
world->camera->m[0]=1.0
world->camera->m[5]=1.0
world->camera->m[10]=1.0
return world->camera
end function
function create_light(byval world as world ptr)as entity ptr
world->light=new entity
world->light->m=cast(single ptr,(cast(ulong,@world->light->matrix_data(0))+15)and &hfffffff0)
world->light->m[0]=1.0
world->light->m[5]=1.0
world->light->m[10]=1.0
return world->light
end function
function create_model(byval world as world ptr)as model ptr
dim as model ptr model=new model
model->next_model=world->first_model
world->first_model=model
return model
end function
function create_entity(byval world as world ptr,byval model as model ptr)as entity ptr
dim as entity ptr mesh=new entity
mesh->m=cast(single ptr,(cast(ulong,@mesh->matrix_data(0))+15)and &hfffffff0)
mesh->m[0]=1.0
mesh->m[5]=1.0
mesh->m[10]=1.0
mesh->model=model
mesh->next_entity=world->first_entity
world->first_entity=mesh
return mesh
end function
constructor gfx_buffer(byval wwidth as long,byval height as long,byval display as long=0)
if display=0 then
this.wwidth=wwidth
this.height=height
this.pitch=wwidth
this.pixels=new ulong[wwidth*height]{any}
this.flags and=&h7fffffff
else
screenres wwidth,height,32,2
screenset 0,1
this.pixels=screenptr()
if this.pixels=0 then end
screeninfo (this.wwidth,this.height,,,this.pitch)
this.pitch shr=2
this.flags or=&h80000000
end if
this.vp_l=0
this.vp_r=wwidth-1
this.vp_t=0
this.vp_b=height-1
end constructor
destructor gfx_buffer()
if (flags and &h80000000)=&h80000000 then
this.pixels=0
else
delete this.pixels
this.pixels=0
end if
if this.depth<>0 then delete this.depth:this.depth=0
if this.normal_data<>0 then delete this.normal_data:this.normal_data=0:this.normal=0
end destructor
sub set_normal(byval buffer as gfx_buffer ptr,_
byval x as ulong,_
byval y as ulong,_
byval nx as single,_
byval ny as single,_
byval nz as single)
if ((x-buffer->vp_l)<=(buffer->vp_r-buffer->vp_l)) and _
((y-buffer->vp_t)<=(buffer->vp_b-buffer->vp_t)) then
dim as single d=1.0/sqr(nx*nx+ny*ny+nz*nz)
buffer->normal[(x+y*buffer->pitch)*4]=nx*d
buffer->normal[(x+y*buffer->pitch)*4+1]=ny*d
buffer->normal[(x+y*buffer->pitch)*4+2]=nz*d
buffer->normal[(x+y*buffer->pitch)*4+3]=0
end if
end sub
sub set_pixel(byval buffer as gfx_buffer ptr,_
byval x as ulong,_
byval y as ulong,_
byval argb as ulong)
if ((x-buffer->vp_l)<=(buffer->vp_r-buffer->vp_l)) and _
((y-buffer->vp_t)<=(buffer->vp_b-buffer->vp_t)) then
buffer->pixels[x+y*buffer->pitch]=argb
end if
end sub
sub set_pixel_alpha(byval buffer as gfx_buffer ptr,_
byval x as long,_
byval y as long,_
byval argb as ulong)
if ((x>=buffer->vp_l)and(x<=buffer->vp_r)and(y>=buffer->vp_t)and(y<=buffer->vp_b)) then
dim as ulong ptr p=buffer->pixels+(x+y*buffer->pitch)
asm
mov eax,dword ptr[p]
mov eax,dword ptr[eax]
mov ebx,dword ptr[argb]' load colour 1
mov edi,ebx
shr edi,24
movzx ecx,ah ' isolate green 1 and move to low byte
movzx edx,bh ' isolate green 2 and move to low byte
sub ebx,eax ' (c2-c1) for red/blue
sub edx,ecx ' (c2-c1) for green
imul ebx,edi ' *alpha for red/blue
imul edx,edi ' *alpha for green
sar ebx,8 ' shift red/blue back to position
add edx,ecx ' +c1 for green
add ebx,eax ' +c1 for red/blue
sub ebx,edx
mov bh,dh ' recombine green with red/blue channel
mov eax,dword ptr[p]
mov dword ptr[eax],ebx 'write colour
end asm
end if
end sub
function get_pixel(byval buffer as gfx_buffer ptr,_
byval x as ulong,_
byval y as ulong)as ulong
if (x<buffer->wwidth) and _
(y<buffer->height) then
return buffer->pixels[x+y*buffer->pitch]
else
return -1
end if
end function
sub draw_image(byval buffer as gfx_buffer ptr,_
byval srce as gfx_buffer ptr,_
byval xp as long,_
byval yp as long)
dim as long x0=xp,y0=yp,x1=x0+srce->wwidth-1,y1=y0+srce->height-1
if x0<buffer->vp_l then x0=buffer->vp_l
if x1>buffer->vp_r then x1=buffer->vp_r
if y0<buffer->vp_t then y0=buffer->vp_t
if y1>buffer->vp_b then y1=buffer->vp_b
dim as long y=y0
dim as ulong ptr dv=buffer->pixels+x0+y*buffer->pitch,sv=srce->pixels+(x0-xp)+(y-yp)*srce->pitch
while y<=y1
dim as long x=x0
dim as ulong pointer d=dv,s=sv
while x<=x1
*d=*s
d+=1
s+=1
x+=1
wend
dv+=buffer->pitch
sv+=srce->pitch
y+=1
wend
end sub
sub draw_masked_image(byval buffer as gfx_buffer ptr,_
byval srce as gfx_buffer ptr,_
byval xp as long,_
byval yp as long,_
byval mask as ulong)
dim as long x0=xp,y0=yp,x1=x0+srce->wwidth-1,y1=y0+srce->height-1
if x0<buffer->vp_l then x0=buffer->vp_l
if x1>buffer->vp_r then x1=buffer->vp_r
if y0<buffer->vp_t then y0=buffer->vp_t
if y1>buffer->vp_b then y1=buffer->vp_b
dim as long y=y0
dim as ulong ptr dv=buffer->pixels+x0+y*buffer->pitch,sv=srce->pixels+(x0-xp)+(y-yp)*srce->pitch
while y<=y1
dim as long x=x0
dim as ulong pointer d=dv,s=sv
while x<=x1
if *s<>mask then *d=*s
d+=1
s+=1
x+=1
wend
dv+=buffer->pitch
sv+=srce->pitch
y+=1
wend
end sub
sub gtriangle(byval buffer as gfx_buffer ptr,_
byval triangle as triangle pointer)
type edge
as single e,x,pad0,pad1
as single b,g,r,a
as single de,dx,dpad0,dpad1
as single db,dg,dr,da
end type
dim as vertex pointer v0=triangle->v0,v1=triangle->v1,v2=triangle->v2
if v2->sy<v0->sy then swap v0,v2
if v1->sy<v0->sy then swap v0,v1 else if v2->sy<v1->sy then swap v1,v2
dim as ubyte ptr edge_bytes=new ubyte[sizeof(edge)+15]{any},scan_bytes=new ubyte[sizeof(edge)+15]{any}
dim as edge ptr edge=cast(edge ptr,cast(ulong,edge_bytes+15)and &hfffffff0)
dim as edge ptr scan=cast(edge ptr,cast(ulong,scan_bytes+15)and &hfffffff0)
dim as single ptr xl=any,xr=any
edge->de=(v1->sx-v0->sx)/(v1->sy-v0->sy)
dim as single dy=1.0/(v2->sy-v0->sy)
edge->dx=(v2->sx-v0->sx)*dy
if edge->dx>edge->de then xl=@edge->e:xr=@edge->x else xl=@edge->x:xr=@edge->e end if
edge->dr=(v2->sr-v0->sr)*dy
edge->dg=(v2->sg-v0->sg)*dy
edge->db=(v2->sb-v0->sb)*dy
dy=v1->sy-v0->sy
dim as single dx=1.0/(v1->sx-(v0->sx+edge->dx*dy))
scan->dr=(v1->sr-(v0->sr+edge->dr*dy))*dx
scan->dg=(v1->sg-(v0->sg+edge->dg*dy))*dx
scan->db=(v1->sb-(v0->sb+edge->db*dy))*dx
dim as integer y_start=v0->sy+0.4999,y_end=v1->sy-0.4999,y_fin=v2->sy-0.4999
if y_start<buffer->vp_t then y_start=buffer->vp_t
if y_end>buffer->vp_b then y_end=buffer->vp_b
if y_fin>buffer->vp_b then y_fin=buffer->vp_b
dim as single d=y_start-v0->sy
edge->e=v0->sx+edge->de*d
edge->x=v0->sx+edge->dx*d
edge->r=v0->sr+edge->dr*d
edge->g=v0->sg+edge->dg*d
edge->b=v0->sb+edge->db*d
asm
mov eax,dword ptr[scan]
movaps xmm0,[eax+offsetof(edge,db)]
mov eax,dword ptr[edge]
movaps xmm3,[eax+offsetof(edge,b)]
movaps xmm4,[eax+offsetof(edge,db)]
end asm
dim as ulong ptr l_start=buffer->pixels+y_start*buffer->pitch
while(y_start<=y_fin)
while(y_start<=y_end)
dim as integer x_start=*xl+0.4999,x_end=*xr-0.4999
if x_start<buffer->vp_l then x_start=buffer->vp_l
x_start and=not(x_start shr 31)
if x_end>buffer->vp_r then x_end=buffer->vp_r
dim as single ddx=x_start-edge->x
asm
movss xmm1,[ddx]
shufps xmm1,xmm1,0
mulps xmm1,xmm0
addps xmm1,xmm3
mov eax,dword ptr[x_start]
mov ebx,dword ptr[x_end]
shl eax,2
shl ebx,2
add eax,dword ptr[l_start]
add ebx,dword ptr[l_start]
cmp eax,ebx
ja gtriangle_no_scanline
gtriangle_tri_loop:
cvtps2pi mm0,xmm1
movhlps xmm2,xmm1
cvtps2pi mm1,xmm2
packuswb mm0,mm1
packuswb mm0,mm0
movd [eax],mm0
add eax,4
addps xmm1,xmm0
cmp eax,ebx
jle gtriangle_tri_loop
gtriangle_no_scanline:
emms
addps xmm3,xmm4
end asm
edge->x+=edge->dx:edge->e+=edge->de:l_start+=buffer->pitch:y_start+=1
wend
if y_start<=y_fin then
y_end=y_fin
edge->de=(v2->sx-v1->sx)/(v2->sy-v1->sy)
dim as single d=y_start-v2->sy
edge->e=v2->sx+edge->de*d
end if
wend
delete edge_bytes
delete scan_bytes
end sub
sub ftriangle(byval buffer as gfx_buffer ptr,byval triangle as triangle pointer)
type edge
as single e,x
as single de,dx
end type
dim as vertex pointer v0=triangle->v0,v1=triangle->v1,v2=triangle->v2
if v2->sy<v0->sy then swap v0,v2
if v1->sy<v0->sy then swap v0,v1 else if v2->sy<v1->sy then swap v1,v2
dim as integer y_start=v0->sy+0.4999,y_end=v1->sy-0.4999,y_fin=v2->sy-0.4999
if y_start<buffer->vp_t then y_start=buffer->vp_t
if y_end>buffer->vp_b then y_end=buffer->vp_b
if y_fin>buffer->vp_b then y_fin=buffer->vp_b
dim as edge edge=any,scan=any
edge.de=(v1->sx-v0->sx)/(v1->sy-v0->sy)
edge.dx=(v2->sx-v0->sx)/(v2->sy-v0->sy)
dim as single ptr xl=any,xr=any
if edge.dx>edge.de then xl=@edge.e:xr=@edge.x else xl=@edge.x:xr=@edge.e end if
dim as single d=y_start-v0->sy
edge.e=v0->sx+edge.de*d
edge.x=v0->sx+edge.dx*d
dim as ulong argb=triangle->argb
dim as ulong ptr l_start=buffer->pixels+y_start*buffer->pitch
while(y_start<=y_fin)
while(y_start<=y_end)
dim as integer x_start=*xl+0.4999,x_end=*xr-0.4999
if x_start<buffer->vp_l then x_start=buffer->vp_l
if x_end>buffer->vp_r then x_end=buffer->vp_r
asm
mov ecx,dword ptr[l_start]
mov eax,dword ptr[x_start]
mov ebx,dword ptr[x_end]
lea ecx,[ecx+ebx*4]
sub eax,ebx
jns ftriangle_no_scanline
mov edx,dword ptr[argb]
ftriangle_tri_loop:
mov dword ptr[ecx+eax*4],edx
inc eax
jng ftriangle_tri_loop
ftriangle_no_scanline:
end asm
edge.x+=edge.dx:edge.e+=edge.de:l_start+=buffer->pitch:y_start+=1
wend
if y_start<=y_fin then
y_end=y_fin
edge.de=(v2->sx-v1->sx)/(v2->sy-v1->sy)
dim as single d=y_start-v2->sy
edge.e=v2->sx+edge.de*d
end if
wend
end sub
sub set_depth(byval buffer as gfx_buffer ptr,_
byval x as ulong,_
byval y as ulong,_
byval depth as single)
if ((x-buffer->vp_l)<=(buffer->vp_r-buffer->vp_l)) and _
((y-buffer->vp_t)<=(buffer->vp_b-buffer->vp_t)) then
buffer->pixels[x+y*buffer->pitch]=1.0/depth
end if
end sub
function get_depth(byval buffer as gfx_buffer ptr,_
byval x as ulong,_
byval y as ulong)as single
if (x<buffer->wwidth) and _
(y<buffer->height) then
return 1.0/buffer->pixels[x+y*buffer->pitch]
else
return -1.0
end if
end function
sub enable_depth(byval buffer as gfx_buffer ptr)
if buffer->depth=0 then
buffer->depth=new single[buffer->pitch*buffer->height]{any}
end if
end sub
sub enable_normal(byval buffer as gfx_buffer ptr)
if buffer->normal=0 then
buffer->normal_data=new ubyte[sizeof(single)*buffer->pitch*buffer->height*4+15]{any}
buffer->normal=cast(single ptr,(cast(ulong,buffer->normal_data)+15)and &hfffffff0)
end if
end sub
sub disable_depth(byval buffer as gfx_buffer ptr)
if buffer->depth<>0 then
delete buffer->depth
buffer->depth=0
end if
end sub
sub clear_buffer(byval buffer as gfx_buffer ptr,_
byval c as ulong=0,_
byval z as single=0.0)
if buffer->depth=0 then
dim as ulong ptr d=buffer->pixels,e=buffer->pixels+buffer->pitch*buffer->height
while d<e
*d=c
d+=1
wend
else
dim as ulong ptr ds=buffer->pixels,e=buffer->pixels+buffer->pitch*buffer->height
dim as single ptr dz=buffer->depth
while ds<e
*dz=z
*ds=c
dz+=1
ds+=1
wend
end if
end sub
sub clear_viewport(byval buffer as gfx_buffer ptr,_
byval c as ulong=0,_
byval z as single=0.0)
if buffer->depth=0 then
dim as long x0=buffer->vp_l,y0=buffer->vp_t,x1=buffer->vp_r,y1=buffer->vp_b
dim as long y=y0
dim as ulong ptr dv=buffer->pixels+x0+y*buffer->pitch
while y<=y1
dim as long x=x0
dim as ulong pointer d=dv
while x<=x1
*d=c
d+=1
x+=1
wend
dv+=buffer->pitch
y+=1
wend
else
dim as long x0=buffer->vp_l,y0=buffer->vp_t,x1=buffer->vp_r,y1=buffer->vp_b
dim as long y=y0
dim as ulong ptr dv=buffer->pixels+x0+y*buffer->pitch
dim as single ptr zv=buffer->depth+x0+y*buffer->pitch
while y<=y1
dim as long x=x0
dim as ulong ptr d=dv
dim as single ptr zp=zv
while x<=x1
*d=c
*zp=z
d+=1
zp+=1
x+=1
wend
dv+=buffer->pitch
zv+=buffer->pitch
y+=1
wend
end if
end sub
sub transition_alpha(byval buffer as gfx_buffer ptr,_
byval x as long,_
byval y as long,_
byval argb as ulong)
if ((x>=buffer->vp_l)and(x<=buffer->vp_r)and(y>=buffer->vp_t)and(y<=buffer->vp_b)) then
dim as ulong ptr p=buffer->pixels+(x+y*buffer->pitch)
asm
mov eax,dword ptr[p]
mov eax,dword ptr[eax]
mov ebx,dword ptr[argb]' load colour 1
mov edi,ebx
shr edi,24
movzx ecx,ah ' isolate green 1 and move to low byte
movzx edx,bh ' isolate green 2 and move to low byte
sub ebx,eax ' (c2-c1) for red/blue
sub edx,ecx ' (c2-c1) for green
imul ebx,edi ' *alpha for red/blue
imul edx,edi ' *alpha for green
sar ebx,8 ' shift red/blue back to position
add edx,ecx ' +c1 for green
add ebx,eax ' +c1 for red/blue
sub ebx,edx
mov bh,dh ' recombine green with red/blue channel
mov eax,dword ptr[p]
mov dword ptr[eax],ebx 'write colour
end asm
end if
end sub
sub draw_triangle(byval buffer as gfx_buffer ptr,byval triangle as triangle ptr)
dim as single ambient=0.1,zero=0.0,m256=256
type edge
as single z,x,e,p1
as single dz,dx,de,p3
as single u0,v0,u1,v1
as single du0,dv0,du1,dv1
as single b,g,r,a
as single db,dg,dr,da
as single cx,cy,cz,cw
as single dcx,dcy,dcz,dcw
as single lx,ly,lz,lw
as single dlx,dly,dlz,dlw
as single mcx,mcy,mcz,mcw
end type
dim as vertex ptr v0=triangle->v0,v1=triangle->v1,v2=triangle->v2
if (v2->sx<v0->sx) then swap v0,v2
if (v1->sx<v0->sx) then swap v0,v1 else if (v2->sx<v1->sx) then swap v1,v2
if (v0->sx<=buffer->vp_r)and(v2->sx>=buffer->vp_l) then
if (v2->sy<v0->sy) then swap v0,v2
if (v1->sy<v0->sy) then swap v0,v1 else if (v2->sy<v1->sy) then swap v1,v2
if (v0->sy<=buffer->vp_b)and(v2->sy>=buffer->vp_t) then
dim as integer y_start=v0->sy+.49999,y_end=v1->sy-.49999,y_fin=v2->sy-.49999
if (y_start<buffer->vp_t) then y_start=buffer->vp_t
if (y_end>buffer->vp_b) then y_end=buffer->vp_b
if (y_fin>buffer->vp_b) then y_fin=buffer->vp_b
dim as ubyte ptr edge_bytes=new ubyte[sizeof(edge)+15]{any}
dim as ubyte ptr scan_bytes=new ubyte[sizeof(edge)+15]{any}
dim as edge ptr edge=cast(edge ptr,(cast(ulong,edge_bytes)+15)and &hfffffff0)
dim as edge ptr scan=cast(edge ptr,(cast(ulong,scan_bytes)+15)and &hfffffff0)
scan->mcx=255.0
scan->mcy=255.0
scan->mcz=255.0
dim as single tw=triangle->texture->wwidth shl 8,th=triangle->texture->height shl 8
v0->su0=v0->u0*tw*v0->sz
v0->sv0=v0->v0*th*v0->sz
v1->su0=v1->u0*tw*v1->sz
v1->sv0=v1->v0*th*v1->sz
v2->su0=v2->u0*tw*v2->sz
v2->sv0=v2->v0*th*v2->sz
dim as ulong v_shift=16-(log(triangle->texture->wwidth)/log(2))
dim as ulong uv_mask=(triangle->texture->wwidth*triangle->texture->height)-1
dim as ulong ptr texels=triangle->texture->pixels
dim as single ptr normals=triangle->texture->normal
dim as single dy01=v1->sy-v0->sy
dim as single dy02=1.0/(v2->sy-v0->sy)
edge->de=(v1->sx-v0->sx)/dy01
edge->dx=(v2->sx-v0->sx)*dy02
edge->dz=(v2->sz-v0->sz)*dy02
dim as single dx_scan=1.0/(v1->sx-(v0->sx+edge->dx*dy01))
dim as single d_y_start=y_start-v0->sy
scan->dz=(v1->sz-(v0->sz+edge->dz*dy01))*dx_scan
edge->e=v0->sx+edge->de*d_y_start
edge->x=v0->sx+edge->dx*d_y_start
edge->z=v0->sz+edge->dz*d_y_start
dim as single ptr xl=any,xr=any
if edge->dx>edge->de then xl=@edge->e:xr=@edge->x else xl=@edge->x:xr=@edge->e end if
#define sse_
#ifdef sse_
asm
movss xmm7,[dy02]
shufps xmm7,xmm7,0
mov eax,[v0]
mov ebx,[v1]
mov ecx,[v2]
mov edx,[edge]
movaps xmm0,[ecx+offsetof(vertex,sb)]
movaps xmm1,[ecx+offsetof(vertex,su0)]
movaps xmm2,[ecx+offsetof(vertex,scx)]
movaps xmm3,[ecx+offsetof(vertex,slx)]
subps xmm0,[eax+offsetof(vertex,sb)]
subps xmm1,[eax+offsetof(vertex,su0)]
subps xmm2,[eax+offsetof(vertex,scx)]
subps xmm3,[eax+offsetof(vertex,slx)]
mulps xmm0,xmm7
mulps xmm1,xmm7
mulps xmm2,xmm7
mulps xmm3,xmm7
movaps [edx+offsetof(edge,db)],xmm0
movaps [edx+offsetof(edge,du0)],xmm1
movaps [edx+offsetof(edge,dcx)],xmm2
movaps [edx+offsetof(edge,dlx)],xmm3
mov ecx,[scan]
movss xmm7,[dy01]
shufps xmm7,xmm7,0
mulps xmm0,xmm7
mulps xmm1,xmm7
mulps xmm2,xmm7
mulps xmm3,xmm7
movaps xmm4,[ebx+offsetof(vertex,sb)]
movaps xmm5,[ebx+offsetof(vertex,su0)]
movaps xmm6,[ebx+offsetof(vertex,scx)]
movaps xmm7,[ebx+offsetof(vertex,slx)]
addps xmm0,[eax+offsetof(vertex,sb)]
addps xmm1,[eax+offsetof(vertex,su0)]
addps xmm2,[eax+offsetof(vertex,scx)]
addps xmm3,[eax+offsetof(vertex,slx)]
subps xmm4,xmm0
subps xmm5,xmm1
subps xmm6,xmm2
subps xmm7,xmm3
movss xmm0,[dx_scan]
shufps xmm0,xmm0,0
mulps xmm4,xmm0
mulps xmm5,xmm0
mulps xmm6,xmm0
mulps xmm7,xmm0
movaps [ecx+offsetof(edge,db)],xmm4
movaps [ecx+offsetof(edge,du0)],xmm5
movaps [ecx+offsetof(edge,dcx)],xmm6
movaps [ecx+offsetof(edge,dlx)],xmm7
movss xmm7,[d_y_start]
shufps xmm7,xmm7,0
movaps xmm0,[edx+offsetof(edge,db)]
movaps xmm1,[edx+offsetof(edge,du0)]
movaps xmm2,[edx+offsetof(edge,dcx)]
movaps xmm3,[edx+offsetof(edge,dlx)]
mulps xmm0,xmm7
mulps xmm1,xmm7
mulps xmm2,xmm7
mulps xmm3,xmm7
addps xmm0,[eax+offsetof(vertex,sb)]
addps xmm1,[eax+offsetof(vertex,su0)]
addps xmm2,[eax+offsetof(vertex,scx)]
addps xmm3,[eax+offsetof(vertex,slx)]
movaps [edx+offsetof(edge,b)],xmm0
movaps [edx+offsetof(edge,u0)],xmm1
movaps [edx+offsetof(edge,cx)],xmm2
movaps [edx+offsetof(edge,lx)],xmm3
end asm
#else
edge->da=(v2->sa-v0->sa)*dy02
edge->dr=(v2->sr-v0->sr)*dy02
edge->dg=(v2->sg-v0->sg)*dy02
edge->db=(v2->sb-v0->sb)*dy02
edge->du0=(v2->su0-v0->su0)*dy02
edge->dv0=(v2->sv0-v0->sv0)*dy02
edge->du1=(v2->su1-v0->su1)*dy02
edge->dv1=(v2->sv1-v0->sv1)*dy02
edge->dcx=(v2->scx-v0->scx)*dy02
edge->dcy=(v2->scy-v0->scy)*dy02
edge->dcz=(v2->scz-v0->scz)*dy02
edge->dcw=(v2->scw-v0->scw)*dy02
edge->dlx=(v2->slx-v0->slx)*dy02
edge->dly=(v2->sly-v0->sly)*dy02
edge->dlz=(v2->slz-v0->slz)*dy02
edge->dlw=(v2->slw-v0->slw)*dy02
scan->da=(v1->sa-(v0->sa+edge->da*dy01))*dx_scan
scan->dr=(v1->sr-(v0->sr+edge->dr*dy01))*dx_scan
scan->dg=(v1->sg-(v0->sg+edge->dg*dy01))*dx_scan
scan->db=(v1->sb-(v0->sb+edge->db*dy01))*dx_scan
scan->du0=(v1->su0-(v0->su0+edge->du0*dy01))*dx_scan
scan->dv0=(v1->sv0-(v0->sv0+edge->dv0*dy01))*dx_scan
scan->du1=(v1->su1-(v0->su1+edge->du1*dy01))*dx_scan
scan->dv1=(v1->sv1-(v0->sv1+edge->dv1*dy01))*dx_scan
scan->dcx=(v1->scx-(v0->scx+edge->dcx*dy01))*dx_scan
scan->dcy=(v1->scy-(v0->scy+edge->dcy*dy01))*dx_scan
scan->dcz=(v1->scz-(v0->scz+edge->dcz*dy01))*dx_scan
scan->dcw=(v1->scw-(v0->scw+edge->dcw*dy01))*dx_scan
scan->dlx=(v1->slx-(v0->slx+edge->dlx*dy01))*dx_scan
scan->dly=(v1->sly-(v0->sly+edge->dly*dy01))*dx_scan
scan->dlz=(v1->slz-(v0->slz+edge->dlz*dy01))*dx_scan
scan->dlw=(v1->slw-(v0->slw+edge->dlw*dy01))*dx_scan
edge->a=v0->sa+edge->da*d_y_start
edge->r=v0->sr+edge->dr*d_y_start
edge->g=v0->sg+edge->dg*d_y_start
edge->b=v0->sb+edge->db*d_y_start
edge->u0=v0->su0+edge->du0*d_y_start
edge->v0=v0->sv0+edge->dv0*d_y_start
edge->u1=v0->su1+edge->du1*d_y_start
edge->v1=v0->sv1+edge->dv1*d_y_start
edge->cx=v0->scx+edge->dcx*d_y_start
edge->cy=v0->scy+edge->dcy*d_y_start
edge->cz=v0->scz+edge->dcz*d_y_start
edge->cw=v0->scw+edge->dcw*d_y_start
edge->lx=v0->slx+edge->dlx*d_y_start
edge->ly=v0->sly+edge->dly*d_y_start
edge->lz=v0->slz+edge->dlz*d_y_start
edge->lw=v0->slw+edge->dlw*d_y_start
#endif
dim as ulong ptr l_start=buffer->pixels+y_start*buffer->pitch
while(y_start<=y_fin)
while(y_start<=y_end)
dim as integer x_start=*xl+0.4999,x_end=*xr-0.4999
if x_start<buffer->vp_l then x_start=buffer->vp_l
if x_end>buffer->vp_r then x_end=buffer->vp_r
dim as single dx_scan=x_start-edge->x
#ifdef sse_
asm
movss xmm7,[dx_scan]
shufps xmm7,xmm7,0
mov eax,[scan]
mov ebx,[edge]
movaps xmm0,[eax+offsetof(edge,db)]
movaps xmm1,[eax+offsetof(edge,du0)]
movaps xmm2,[eax+offsetof(edge,dcx)]
movaps xmm3,[eax+offsetof(edge,dlx)]
movss xmm4,[eax+offsetof(edge,dz)]
mulps xmm0,xmm7
mulps xmm1,xmm7
mulps xmm2,xmm7
mulps xmm3,xmm7
mulss xmm4,xmm7
addps xmm0,[ebx+offsetof(edge,b)]
addps xmm1,[ebx+offsetof(edge,u0)]
addps xmm2,[ebx+offsetof(edge,cx)]
addps xmm3,[ebx+offsetof(edge,lx)]
addss xmm4,[ebx+offsetof(edge,z)]
end asm
#else
scan->r=edge->r+scan->dr*dx_scan
scan->g=edge->g+scan->dg*dx_scan
scan->b=edge->b+scan->db*dx_scan
#endif
dim as ulong ptr p_start=l_start+x_start,p_end=l_start+x_end
while(p_start<=p_end)
#ifdef sse_
asm
mov eax,[p_start]
mov edi,[texels]
mov esi,[normals]
shufps xmm4,xmm4,0
rcpss xmm5,xmm4 '1/z
shufps xmm5,xmm5,0 '1/z 1/z 1/z 1/z
'movaps xmm6,xmm5
mulps xmm5,xmm1 'tex coords
cvtps2pi mm2,xmm5 'convert to int
pshufw mm2,mm2,8 'get lower 16 bits of u/v
mov ecx,[v_shift] '
movd edx,mm2 '
shr edx,8 'get rid of fraction
shl dx,cl 'combine uv
shr edx,cl
and edx,[uv_mask] 'mask for wrapping
shl edx,4
movaps xmm5,[esi+edx]
movaps xmm6,xmm3
movaps xmm7,xmm3
mulps xmm6,xmm6
mulps xmm7,xmm5
haddps xmm6,xmm6
haddps xmm7,xmm7
haddps xmm6,xmm6
haddps xmm7,xmm7
rsqrtss xmm6,xmm6
mulss xmm6,xmm7
shufps xmm6,xmm6,0
mulps xmm6,xmm0
divps xmm6,xmm4
cvtps2pi mm0,xmm6
movhlps xmm6,xmm6
cvtps2pi mm1,xmm6
packuswb mm0,mm1
shr edx,2
movd mm1,[edi+edx]
pxor mm7,mm7
punpcklbw mm1,mm7 'combine tex and colour
pmullw mm0,mm1
psrlw mm0,8
shl edx,2
movaps xmm5,[esi+edx]
mulps xmm5,xmm3
haddps xmm5,xmm5
haddps xmm5,xmm5
addss xmm5,xmm5
shufps xmm5,xmm5,0
mulps xmm5,[esi+edx]
movaps xmm6,xmm3
subps xmm6,xmm5
mulps xmm6,xmm2
haddps xmm6,xmm6
haddps xmm6,xmm6
movaps xmm7,xmm3
mulps xmm7,xmm7
haddps xmm7,xmm7
haddps xmm7,xmm7
movaps xmm5,xmm2
mulps xmm5,xmm5
haddps xmm5,xmm5
haddps xmm5,xmm5
mulss xmm5,xmm7
rsqrtss xmm5,xmm5
mulss xmm5,xmm6
minss xmm5,[zero]
mulss xmm5,xmm5
mulss xmm5,xmm5
mulss xmm5,[m256]
cvtps2pi mm2,xmm5
pshufw mm2,mm2,0
paddusw mm0,mm2
packuswb mm0,mm0
movd [eax],mm0 'write pixel
mov eax,[scan]
addps xmm0,[eax+offsetof(edge,db)]
addps xmm1,[eax+offsetof(edge,du0)]
addps xmm2,[eax+offsetof(edge,dcx)]
addps xmm3,[eax+offsetof(edge,dlx)]
addss xmm4,[eax+offsetof(edge,dz)]
end asm
#else
*p_start=(scan->r shl 16)or(scan->g shl 8)or(scan->b)
scan->r+=scan->dr
scan->g+=scan->dg
scan->b+=scan->db
#endif
p_start+=1
wend
#ifdef sse_
asm
emms
mov eax,[edge]
movaps xmm0,[eax+offsetof(edge,b)]
movaps xmm1,[eax+offsetof(edge,u0)]
movaps xmm2,[eax+offsetof(edge,cx)]
movaps xmm3,[eax+offsetof(edge,lx)]
movaps xmm4,[eax+offsetof(edge,z)]
addps xmm0,[eax+offsetof(edge,db)]
addps xmm1,[eax+offsetof(edge,du0)]
addps xmm2,[eax+offsetof(edge,dcx)]
addps xmm3,[eax+offsetof(edge,dlx)]
addps xmm4,[eax+offsetof(edge,dz)]
movaps [eax+offsetof(edge,b)],xmm0
movaps [eax+offsetof(edge,u0)],xmm1
movaps [eax+offsetof(edge,cx)],xmm2
movaps [eax+offsetof(edge,lx)],xmm3
movaps [eax+offsetof(edge,z)],xmm4
end asm
#else
edge->r+=edge->dr
edge->g+=edge->dg
edge->b+=edge->db
edge->x+=edge->dx
edge->e+=edge->de
#endif
l_start+=buffer->pitch
y_start+=1
wend
if y_start<=y_fin then
y_end=y_fin
edge->de=(v2->sx-v1->sx)/(v2->sy-v1->sy)
dim as single d=y_start-v2->sy
edge->e=v2->sx+edge->de*d
end if
wend
delete edge_bytes
delete scan_bytes
end if
end if
end sub
sub transform_vertices(byval buffer as gfx_buffer ptr,byval world as world pointer,byval mesh as entity pointer)
dim as entity pointer cam=world->camera
dim as single w=buffer->wwidth*.5,h=buffer->height*.5
dim as single lig_xt=world->light->m[16]-mesh->m[16]
dim as single lig_yt=world->light->m[17]-mesh->m[17]
dim as single lig_zt=world->light->m[18]-mesh->m[18]
dim as single lx=mesh->m[0]*lig_xt+mesh->m[4]*lig_yt+mesh->m[8]*lig_zt
dim as single ly=mesh->m[1]*lig_xt+mesh->m[5]*lig_yt+mesh->m[9]*lig_zt
dim as single lz=mesh->m[2]*lig_xt+mesh->m[6]*lig_yt+mesh->m[10]*lig_zt
dim as single cam_xt=mesh->m[16]-cam->m[16]
dim as single cam_yt=mesh->m[17]-cam->m[17]
dim as single cam_zt=mesh->m[18]-cam->m[18]
dim as single cx=-(mesh->m[0]*cam_xt+mesh->m[4]*cam_yt+mesh->m[8]*cam_zt)
dim as single cy=-(mesh->m[1]*cam_xt+mesh->m[5]*cam_yt+mesh->m[9]*cam_zt)
dim as single cz=-(mesh->m[2]*cam_xt+mesh->m[6]*cam_yt+mesh->m[10]*cam_zt)
dim as single ox=cam->m[0]*cam_xt+cam->m[4]*cam_yt+cam->m[8]*cam_zt
dim as single oy=cam->m[1]*cam_xt+cam->m[5]*cam_yt+cam->m[9]*cam_zt
dim as single oz=cam->m[2]*cam_xt+cam->m[6]*cam_yt+cam->m[10]*cam_zt
dim as single ux0=(cam->m[0]*mesh->m[0]+cam->m[4]*mesh->m[4]+cam->m[8]*mesh->m[8])
dim as single ux1=(cam->m[0]*mesh->m[1]+cam->m[4]*mesh->m[5]+cam->m[8]*mesh->m[9])
dim as single ux2=(cam->m[0]*mesh->m[2]+cam->m[4]*mesh->m[6]+cam->m[8]*mesh->m[10])
dim as single uy0=(cam->m[1]*mesh->m[0]+cam->m[5]*mesh->m[4]+cam->m[9]*mesh->m[8])
dim as single uy1=(cam->m[1]*mesh->m[1]+cam->m[5]*mesh->m[5]+cam->m[9]*mesh->m[9])
dim as single uy2=(cam->m[1]*mesh->m[2]+cam->m[5]*mesh->m[6]+cam->m[9]*mesh->m[10])
dim as single uz0=(cam->m[2]*mesh->m[0]+cam->m[6]*mesh->m[4]+cam->m[10]*mesh->m[8])
dim as single uz1=(cam->m[2]*mesh->m[1]+cam->m[6]*mesh->m[5]+cam->m[10]*mesh->m[9])
dim as single uz2=(cam->m[2]*mesh->m[2]+cam->m[6]*mesh->m[6]+cam->m[10]*mesh->m[10])
dim as vertex pointer vert=mesh->model->first_vertex
while vert<>0
vert->rx=vert->x*ux0+vert->y*ux1+vert->z*ux2+ox
vert->ry=vert->x*uy0+vert->y*uy1+vert->z*uy2+oy
vert->rz=vert->x*uz0+vert->y*uz1+vert->z*uz2+oz
vert->sz=1.0/vert->rz
vert->sx=w+w*2.0*(vert->rx)*(vert->sz)
vert->sy=h-w*2.0*(vert->ry)*(vert->sz)
'vert->su0=vert->u0*vert->sz
'vert->sv0=vert->v0*vert->sz
vert->sr=vert->r*256.0*vert->sz
vert->sg=vert->g*256.0*vert->sz
vert->sb=vert->b*256.0*vert->sz
dim as single lpx=lx-vert->x,lpy=ly-vert->y,lpz=lz-vert->z
vert->slx=(lpx*vert->bx+lpy*vert->by+lpz*vert->bz)*vert->sz
vert->sly=(lpx*vert->tx+lpy*vert->ty+lpz*vert->tz)*vert->sz
vert->slz=(lpx*vert->nx+lpy*vert->ny+lpz*vert->nz)*vert->sz
dim as single cpx=cx-vert->x,cpy=cy-vert->y,cpz=cz-vert->z
vert->scx=(cpx*vert->bx+cpy*vert->by+cpz*vert->bz)*vert->sz
vert->scy=(cpx*vert->tx+cpy*vert->ty+cpz*vert->tz)*vert->sz
vert->scz=(cpx*vert->nx+cpy*vert->ny+cpz*vert->nz)*vert->sz
vert=vert->next_vertex
wend
end sub
sub render_mesh(byval dest as gfx_buffer pointer,byval mesh as entity pointer)
dim as triangle pointer tri=mesh->model->first_triangle
while tri<>0
if (tri->v0->rz>4.0)and(tri->v1->rz>4.0)and(tri->v2->rz>4.0) then
dim as single dx0=tri->v1->sx-tri->v0->sx
dim as single dy0=tri->v1->sy-tri->v0->sy
dim as single dx1=tri->v2->sx-tri->v0->sx
dim as single dy1=tri->v2->sy-tri->v0->sy
if (dx0*dy1)>(dx1*dy0) then draw_triangle(dest,tri)
end if
tri=tri->next_triangle
wend
end sub
sub render_world(byval dest as gfx_buffer pointer,byval world as world pointer)
dim as entity pointer mesh=world->first_entity
while mesh<>0
transform_vertices(dest,world,mesh)
render_mesh(dest,mesh)
mesh=mesh->next_entity
wend
end sub
function add_vertex(byval model as model ptr,_
byval x as single,_
byval y as single,_
byval z as single,_
byval u as single=0.0,_
byval v as single=0.0)as vertex ptr
dim as vertex_data ptr dat=new vertex_data
dim as vertex ptr vertex=cast(vertex ptr,(cast(ulong,dat)+15)and &hfffffff0)
vertex->vertex_data=dat
vertex->x=x
vertex->y=y
vertex->z=z
vertex->u0=u
vertex->v0=v
vertex->r=1.0
vertex->g=1.0
vertex->b=1.0
vertex->next_vertex=model->first_vertex
model->first_vertex=vertex
function=vertex
end function
sub set_vertex_colour(byval v as vertex pointer,byval r as single,byval g as single,byval b as single)
v->r=r
v->g=g
v->b=b
end sub
sub set_vertex_texture(byval vertex as vertex ptr,byval v as single,byval u as single)
vertex->u0=u
vertex->v0=v
end sub
function add_triangle(byval model as model ptr,_
byval v0 as vertex ptr,_
byval v1 as vertex ptr,_
byval v2 as vertex ptr,_
byval texture as gfx_buffer ptr)as triangle ptr
dim as triangle ptr triangle=new triangle
triangle->v0=v0
triangle->v1=v1
triangle->v2=v2
triangle->texture=texture
triangle->next_triangle=model->first_triangle
model->first_triangle=triangle
function=triangle
end function
sub normalise_model(byval model as model ptr)
dim as triangle ptr tri=model->first_triangle
while tri<>0
dim as vertex ptr v0=tri->v0,v1=tri->v1,v2=tri->v2
dim as single vx0=v1->x-v0->x,vy0=v1->y-v0->y,vz0=v1->z-v0->z
dim as single vx1=v2->x-v0->x,vy1=v2->y-v0->y,vz1=v2->z-v0->z
dim as single d=1.0/sqr(vx0*vx0+vy0*vy0+vz0*vz0)
vx0*=d
vy0*=d
vz0*=d
d=1.0/sqr(vx1*vx1+vy1*vy1+vz1*vz1)
vx1*=d
vy1*=d
vz1*=d
tri->nx=vy0*vz1-vz0*vy1
tri->ny=vz0*vx1-vx0*vz1
tri->nz=vx0*vy1-vy0*vx1
'dim as single
d=1.0/sqr(tri->nx^2+tri->ny^2+tri->nz^2)
tri->nx*=d
tri->ny*=d
tri->nz*=d
dim as single du0=v1->u0-v0->u0
dim as single dv0=v1->v0-v0->v0
dim as single du1=v2->u0-v0->u0
dim as single dv1=v2->v0-v0->v0
d=1.0/sqr(du0*du0+dv0*dv0)
du0*=d
dv0*=d
d=1.0/sqr(du1*du1+dv1*dv1)
du1*=d
dv1*=d
d=1.0'/(du0*dv1-du1*dv0)
tri->bx=d*(dv1*vx0-dv0*vx1)
tri->by=d*(dv1*vy0-dv0*vy1)
tri->bz=d*(dv1*vz0-dv0*vz1)
tri->tx=d*(-du1*vx0-du0*vx1)
tri->ty=d*(-du1*vy0-du0*vy1)
tri->tz=d*(-du1*vz0-du0*vz1)
d=1.0/sqr(tri->tx*tri->tx+tri->ty*tri->ty+tri->tz*tri->tz)
tri->tx*=d
tri->ty*=d
tri->tz*=d
d=1.0/sqr(tri->bx*tri->bx+tri->by*tri->by+tri->bz*tri->bz)
tri->bx*=d
tri->by*=d
tri->bz*=d
d=1/sqr(vx0^2+vy0^2+vz0^2)
vx0*=d:vy0*=d:vz0*=d
d=1/sqr(vx1^2+vy1^2+vz1^2)
vx1*=d:vy1*=d:vz1*=d
d=acos(vx0*vx1+vy0*vy1+vz0*vz1)
v0->nx+=d*tri->nx
v0->ny+=d*tri->ny
v0->nz+=d*tri->nz
v0->tx+=d*tri->tx
v0->ty+=d*tri->ty
v0->tz+=d*tri->tz
v0->bx+=d*tri->bx
v0->by+=d*tri->by
v0->bz+=d*tri->bz
vx0=v0->x-v1->x:vy0=v0->y-v1->y:vz0=v0->z-v1->z
vx1=v2->x-v1->x:vy1=v2->y-v1->y:vz1=v2->z-v1->z
d=1/sqr(vx0^2+vy0^2+vz0^2)
vx0*=d:vy0*=d:vz0*=d
d=1/sqr(vx1^2+vy1^2+vz1^2)
vx1*=d:vy1*=d:vz1*=d
d=acos(vx0*vx1+vy0*vy1+vz0*vz1)
v1->nx+=d*tri->nx
v1->ny+=d*tri->ny
v1->nz+=d*tri->nz
v1->tx+=d*tri->tx
v1->ty+=d*tri->ty
v1->tz+=d*tri->tz
v1->bx+=d*tri->bx
v1->by+=d*tri->by
v1->bz+=d*tri->bz
vx0=v0->x-v2->x:vy0=v0->y-v2->y:vz0=v0->z-v2->z
vx1=v1->x-v2->x:vy1=v1->y-v2->y:vz1=v1->z-v2->z
d=1/sqr(vx0^2+vy0^2+vz0^2)
vx0*=d:vy0*=d:vz0*=d
d=1/sqr(vx1^2+vy1^2+vz1^2)
vx1*=d:vy1*=d:vz1*=d
d=acos(vx0*vx1+vy0*vy1+vz0*vz1)
v2->nx+=d*tri->nx
v2->ny+=d*tri->ny
v2->nz+=d*tri->nz
v2->tx+=d*tri->tx
v2->ty+=d*tri->ty
v2->tz+=d*tri->tz
v2->bx+=d*tri->bx
v2->by+=d*tri->by
v2->bz+=d*tri->bz
tri=tri->next_triangle
wend
dim as vertex ptr vert=model->first_vertex
while vert<>0
dim as single d=1.0/sqr(vert->nx^2+vert->ny^2+vert->nz^2)
vert->nx*=d
vert->ny*=d
vert->nz*=d
d=1.0/sqr(vert->tx^2+vert->ty^2+vert->tz^2)
vert->tx*=d
vert->ty*=d
vert->tz*=d
d=1.0/sqr(vert->bx^2+vert->by^2+vert->bz^2)
vert->bx*=d
vert->by*=d
vert->bz*=d
vert=vert->next_vertex
wend
end sub
sub translate_entity(byval entity as entity pointer,byval x as single,byval y as single,byval z as single)
entity->m[16]+=x
entity->m[17]+=y
entity->m[18]+=z
end sub
sub position_entity(byval entity as entity pointer,byval x as single,byval y as single,byval z as single)
entity->m[16]=x
entity->m[17]=y
entity->m[18]=z
end sub
sub move_entity(entity as entity pointer,x as single,y as single,z as single)
entity->m[16]+=x*entity->m[0]+y*entity->m[1]+z*entity->m[3]
entity->m[17]+=x*entity->m[4]+y*entity->m[5]+z*entity->m[6]
entity->m[18]+=x*entity->m[8]+y*entity->m[9]+z*entity->m[10]
end sub
sub rotate_entity(byval entity as entity pointer,byval b as single,byval a as single,byval c as single)
a*=3.1415926/180.0
b*=3.1415926/180.0
c*=3.1415926/180.0
dim csa as single=cos(a)
dim sna as single=sin(a)
dim csb as single=cos(b)
dim snb as single=sin(b)
dim csc as single=cos(-c)
dim snc as single=sin(-c)
dim x as single
dim y as single
dim z as single
x=entity->m[0]*csa+entity->m[8]*sna
z=entity->m[8]*csa-entity->m[0]*sna
entity->m[8]=z*csb+entity->m[4]*snb
y=entity->m[4]*csb-z*snb
entity->m[0]=x*csc+y*snc
entity->m[4]=y*csc-x*snc
x=entity->m[1]*csa+entity->m[9]*sna
z=entity->m[9]*csa-entity->m[1]*sna
entity->m[9]=z*csb+entity->m[5]*snb
y=entity->m[5]*csb-z*snb
entity->m[1]=x*csc+y*snc
entity->m[5]=y*csc-x*snc
x=entity->m[2]*csa+entity->m[10]*sna
z=entity->m[10]*csa-entity->m[2]*sna
entity->m[10]=z*csb+entity->m[6]*snb
y=entity->m[6]*csb-z*snb
entity->m[2]=x*csc+y*snc
entity->m[6]=y*csc-x*snc
end sub
sub turn_entity(byval entity as entity pointer,byval b as single,byval a as single,byval c as single)
a*=3.1415926/180.0
b*=3.1415926/180.0
c*=3.1415926/180.0
dim csa as single=cos(-a)
dim sna as single=sin(-a)
dim csb as single=cos(-b)
dim snb as single=sin(-b)
dim csc as single=cos(c)
dim snc as single=sin(c)
dim x as single
dim y as single
dim z as single
x=entity->m[0]*csa+entity->m[2]*sna
z=entity->m[2]*csa-entity->m[0]*sna
entity->m[2]=z*csb+entity->m[1]*snb
y=entity->m[1]*csb-z*snb
entity->m[0]=x*csc+y*snc
entity->m[1]=y*csc-x*snc
x=entity->m[4]*csa+entity->m[6]*sna
z=entity->m[6]*csa-entity->m[4]*sna
entity->m[6]=z*csb+entity->m[5]*snb
y=entity->m[5]*csb-z*snb
entity->m[4]=x*csc+y*snc
entity->m[5]=y*csc-x*snc
x=entity->m[8]*csa+entity->m[10]*sna
z=entity->m[10]*csa-entity->m[8]*sna
entity->m[10]=z*csb+entity->m[9]*snb
y=entity->m[9]*csb-z*snb
entity->m[8]=x*csc+y*snc
entity->m[9]=y*csc-x*snc
end sub
sub copy_rotation(byval dst as entity ptr,_
byval src as entity ptr)
dst->m[0]=src->m[0]
dst->m[1]=src->m[1]
dst->m[2]=src->m[2]
dst->m[4]=src->m[4]
dst->m[5]=src->m[5]
dst->m[6]=src->m[6]
dst->m[8]=src->m[8]
dst->m[9]=src->m[9]
dst->m[10]=src->m[10]
end sub
sub copy_position(byval dst as entity ptr,_
byval src as entity ptr)
dst->m[16]=src->m[16]
dst->m[17]=src->m[17]
dst->m[18]=src->m[18]
end sub
type edge
x as single
e as single
r as single
g as single
b as single
u as single
v as single
uf as single
vf as single
z as single
dx as single
de as single
dr as single
dg as single
db as single
du as single
dv as single
duf as single
dvf as single
dz as single
end type
function create_test_texture(byval w as long,byval h as long)as gfx_buffer ptr
dim as gfx_buffer ptr texture=new gfx_buffer(w,h)
dim as single height(0 to w-1,0 to h-1)
for y as integer=0 to h-1
for x as integer=0 to w-1
dim as single r=sqr((y-h/2)^2+(x-w/2)^2)
height(x,y)=20*cos(r*0.2)+rnd*20
if ((x and 15)<5)or((y and 15)<5) then height(x,y)=-20
next
next
enable_normal(texture)
for y as long=0 to h-1
for x as long=0 to w-1
set_pixel(texture,x,y,rnd*&hffffff)
if ((x and 15)=0)or((y and 15)=0) then set_pixel(texture,x,y,&hffffff)
'set_pixel(texture,x,y,&hff00ff)
dim as single dx,dy
dx=height((x+1)and &hff,y)-height((x-1)and &hff,y)
dy=height(x,(y+1)and &hff)-height(x,(y-1)and &hff)
set_normal(texture,x,y,dx,dy,40)
if 1=2 then
if x<y then
if (255-x)<y then
set_normal(texture,x,y,0,-10,40)
else
set_normal(texture,x,y,10,0,40)
end if
else
if (255-x)<y then
set_normal(texture,x,y,-10,0,40)
else
set_normal(texture,x,y,0,10,40)
end if
end if
end if
'set_normal(texture,x,y,0,0,10)
next
next
function=texture
end function
function create_cube_model(byval world as world ptr,byval size as single)as model ptr
dim as gfx_buffer ptr texture=create_test_texture(256,256)
dim as model ptr model=create_model(world)
dim as vertex ptr v0,v1,v2,v3
v0=add_vertex(model,-size, size,-size,0,0)
v1=add_vertex(model, size, size,-size,1,0)
v2=add_vertex(model, size,-size,-size,1,1)
v3=add_vertex(model,-size,-size,-size,0,1)
set_vertex_colour(v0,0,0,1)
set_vertex_colour(v1,0,1,0)
set_vertex_colour(v2,1,0,0)
set_vertex_colour(v3,1,0,1)
set_vertex_texture(v0,0,0)
set_vertex_texture(v1,2,0)
set_vertex_texture(v2,2,2)
set_vertex_texture(v3,0,2)
add_triangle(model,v0,v1,v2,texture)
add_triangle(model,v2,v3,v0,texture)
v0=add_vertex(model,-size, size, size,0,0)
v1=add_vertex(model,-size, size,-size,1,0)
v2=add_vertex(model,-size,-size,-size,1,1)
v3=add_vertex(model,-size,-size, size,0,1)
set_vertex_colour(v0,0,0,1)
set_vertex_colour(v1,0,1,0)
set_vertex_colour(v2,1,0,0)
set_vertex_colour(v3,1,0,1)
set_vertex_texture(v0,0,0)
set_vertex_texture(v1,1,0)
set_vertex_texture(v2,1,1)
set_vertex_texture(v3,0,1)
add_triangle(model,v0,v1,v2,texture)
add_triangle(model,v2,v3,v0,texture)
v0=add_vertex(model, size, size, size,0,0)
v1=add_vertex(model,-size, size, size,1,0)
v2=add_vertex(model,-size,-size, size,1,1)
v3=add_vertex(model, size,-size, size,0,1)
set_vertex_colour(v0,0,0,1)
set_vertex_colour(v1,0,1,0)
set_vertex_colour(v2,1,0,0)
set_vertex_colour(v3,1,0,1)
set_vertex_texture(v0,0,0)
set_vertex_texture(v1,1,0)
set_vertex_texture(v2,1,1)
set_vertex_texture(v3,0,1)
add_triangle(model,v0,v1,v2,texture)
add_triangle(model,v2,v3,v0,texture)
v0=add_vertex(model, size, size,-size,0,0)
v1=add_vertex(model, size, size, size,1,0)
v2=add_vertex(model, size,-size, size,1,1)
v3=add_vertex(model, size,-size,-size,0,1)
set_vertex_colour(v0,0,0,1)
set_vertex_colour(v1,0,1,0)
set_vertex_colour(v2,1,0,0)
set_vertex_colour(v3,1,0,1)
set_vertex_texture(v0,0,0)
set_vertex_texture(v1,1,0)
set_vertex_texture(v2,1,1)
set_vertex_texture(v3,0,1)
add_triangle(model,v0,v1,v2,texture)
add_triangle(model,v2,v3,v0,texture)
v0=add_vertex(model,-size, size, size,0,0)
v1=add_vertex(model, size, size, size,1,0)
v2=add_vertex(model, size, size,-size,1,1)
v3=add_vertex(model,-size, size,-size,0,1)
set_vertex_colour(v0,0,0,1)
set_vertex_colour(v1,0,1,0)
set_vertex_colour(v2,1,0,0)
set_vertex_colour(v3,1,0,1)
set_vertex_texture(v0,0,0)
set_vertex_texture(v1,1,0)
set_vertex_texture(v2,1,1)
set_vertex_texture(v3,0,1)
add_triangle(model,v0,v1,v2,texture)
add_triangle(model,v2,v3,v0,texture)
v0=add_vertex(model,-size,-size,-size,0,0)
v1=add_vertex(model, size,-size,-size,1,0)
v2=add_vertex(model, size,-size, size,1,1)
v3=add_vertex(model,-size,-size, size,0,1)
set_vertex_colour(v0,0,0,1)
set_vertex_colour(v1,0,1,0)
set_vertex_colour(v2,1,0,0)
set_vertex_colour(v3,1,0,1)
set_vertex_texture(v0,0,0)
set_vertex_texture(v1,1,0)
set_vertex_texture(v2,1,1)
set_vertex_texture(v3,0,1)
add_triangle(model,v0,v1,v2,texture)
add_triangle(model,v2,v3,v0,texture)
normalise_model(model)
return model
end function
function create_cube_model2(byval world as world ptr,byval size as single)as model ptr
dim as gfx_buffer ptr texture=create_test_texture(256,256)
dim as model ptr model=create_model(world)
dim as vertex ptr v0,v1,v2,v3,v4,v5,v6,v7
v0=add_vertex(model,-size,-size,-size,0,1)
v1=add_vertex(model,-size,-size, size,1,1)
v2=add_vertex(model, size,-size, size,0,1)
v3=add_vertex(model, size,-size,-size,1,1)
v4=add_vertex(model,-size, size,-size,0,0)
v5=add_vertex(model,-size, size, size,1,0)
v6=add_vertex(model, size, size, size,0,0)
v7=add_vertex(model, size, size,-size,1,0)
'set_vertex_colour(v0,0,0,1)
'set_vertex_colour(v1,0,1,0)
'set_vertex_colour(v2,1,0,0)
'set_vertex_colour(v3,1,0,1)
'set_vertex_texture(v0,0,0)
'set_vertex_texture(v1,2,0)
'set_vertex_texture(v2,2,2)
'set_vertex_texture(v3,0,2)
add_triangle(model,v0,v4,v7,texture)
add_triangle(model,v7,v3,v0,texture)
'v0=add_vertex(model,-size, size, size,0,0)
'v1=add_vertex(model,-size, size,-size,1,0)
'v2=add_vertex(model,-size,-size,-size,1,1)
'v3=add_vertex(model,-size,-size, size,0,1)
'set_vertex_colour(v0,0,0,1)
'set_vertex_colour(v1,0,1,0)
'set_vertex_colour(v2,1,0,0)
'set_vertex_colour(v3,1,0,1)
'set_vertex_texture(v0,0,0)
'set_vertex_texture(v1,1,0)
'set_vertex_texture(v2,1,1)
'set_vertex_texture(v3,0,1)
add_triangle(model,v1,v5,v4,texture)
add_triangle(model,v4,v0,v1,texture)
'v0=add_vertex(model, size, size, size,0,0)
'v1=add_vertex(model,-size, size, size,1,0)
'v2=add_vertex(model,-size,-size, size,1,1)
'v3=add_vertex(model, size,-size, size,0,1)
'set_vertex_colour(v0,0,0,1)
'set_vertex_colour(v1,0,1,0)
'set_vertex_colour(v2,1,0,0)
'set_vertex_colour(v3,1,0,1)
'set_vertex_texture(v0,0,0)
'set_vertex_texture(v1,1,0)
'set_vertex_texture(v2,1,1)
'set_vertex_texture(v3,0,1)
add_triangle(model,v2,v6,v5,texture)
add_triangle(model,v5,v1,v2,texture)
'v0=add_vertex(model, size, size,-size,0,0)
'v1=add_vertex(model, size, size, size,1,0)
'v2=add_vertex(model, size,-size, size,1,1)
'v3=add_vertex(model, size,-size,-size,0,1)
'set_vertex_colour(v0,0,0,1)
'set_vertex_colour(v1,0,1,0)
'set_vertex_colour(v2,1,0,0)
'set_vertex_colour(v3,1,0,1)
'set_vertex_texture(v0,0,0)
'set_vertex_texture(v1,1,0)
'set_vertex_texture(v2,1,1)
'set_vertex_texture(v3,0,1)
add_triangle(model,v3,v7,v6,texture)
add_triangle(model,v6,v2,v3,texture)
'v0=add_vertex(model,-size, size, size,0,0)
'v1=add_vertex(model, size, size, size,1,0)
'v2=add_vertex(model, size, size,-size,1,1)
'v3=add_vertex(model,-size, size,-size,0,1)
'set_vertex_colour(v0,0,0,1)
'set_vertex_colour(v1,0,1,0)
'set_vertex_colour(v2,1,0,0)
'set_vertex_colour(v3,1,0,1)
'set_vertex_texture(v0,0,0)
'set_vertex_texture(v1,1,0)
'set_vertex_texture(v2,1,1)
'set_vertex_texture(v3,0,1)
'add_triangle(model,v4,v5,v6,texture)
'add_triangle(model,v6,v7,v4,texture)
'v0=add_vertex(model,-size,-size,-size,0,0)
'v1=add_vertex(model, size,-size,-size,1,0)
'v2=add_vertex(model, size,-size, size,1,1)
'v3=add_vertex(model,-size,-size, size,0,1)
'set_vertex_colour(v0,0,0,1)
'set_vertex_colour(v1,0,1,0)
'set_vertex_colour(v2,1,0,0)
'set_vertex_colour(v3,1,0,1)
'set_vertex_texture(v0,0,0)
'set_vertex_texture(v1,1,0)
'set_vertex_texture(v2,1,1)
'set_vertex_texture(v3,0,1)
'add_triangle(model,v0,v3,v2,texture)
'add_triangle(model,v2,v1,v0,texture)
normalise_model(model)
return model
end function
sub main
dim as gfx_buffer ptr display=new gfx_buffer(640,480,1)
dim as world ptr world=create_world()
dim as entity ptr camera=create_camera(world)
dim as entity ptr light=create_light(world)
position_entity light,500,0,-500
dim as entity ptr cube=create_entity(world,create_cube_model(world,100))
move_entity camera,0,0,-500
dim as double t=timer,delta=timer
while inkey<>chr(27)
dim as double tt=timer
dim as double fps=1.0/(tt-t)
t=tt
'windowtitle(str$(fps))
while delta<timer
turn_entity(cube,0.08,0.01,0)
rotate_entity(cube,.11,0,.13)
delta+=.01
wend
render_world(display,world)
flip
cls
wend
end sub
main
end