These are totally local in some cases. They don't work between functions or even gosubs sometimes. Too bad too as I could really use some global versions of these commands at bare minimum they need to work between gosubs. Getting distances from vetors is many time faster than sqrt. But when you have to create them each test it is a little slower than sqrt.
Why does the vector3 work with this code:
sync on : sync rate 0 : autocam off
position camera 0, 12, -10
make object cube 1,10
make object cube 2,10
make matrix 1,500,500,32,32
position matrix 1,-250,0,-250
position object 1,-10,5,20
position object 2,10,20,20
null3D=make vector3(1)
do
gosub range3D
set cursor 5,5
print "working : ", result#
sync
loop
null3D=delete vector3(1)
rem distance between 2 objects
range3D:
ax#=object position x(1)
ay#=object position y(1)
az#=object position z(1)
bx#=object position x(2)
by#=object position y(2)
bz#=object position z(2)
set vector3 1,ax#-bx#,ay#-by#,az#-bz# : result#=length vector3(1)
return
And not in this code (warning this code requires the DKShop plugin (
http://forum.thegamecreators.com/?m=forum_view&t=67196&b=5)as DBP doesn't have a way to extract matrix4 elment data. Also uses the media from the advanced terrain demo. You can just copy the code overthe example 1 demo.
`Frustum culling added by Lost In Thought
`Ported over frum this guide by Mark Morley
`http://crownandcutlass.com/features/technicaldetails/frustum.html
` Advanced Terrain System - Example 1
` sky textures from - SkyMatter
` heightmap created by - David Smith ( infiniteloop@optushome.com.au )
` terrain base texture - generated from Advanced Terrain System Plus
` demo by - TGC
` set up display and camera
sync on
backdrop on
autocam off
set camera range 0.5, 3000
` movement
g_fSpeed# = 0.05
g_fTurn# = 0.3
` set the directory to media
set dir "media"
` load base and detail texture
load image "texture.bmp", 1
load image "detail.tga", 2
make object terrain 1 ` create the terrain object
set terrain heightmap 1, "map.bmp" ` set the heightmap
set terrain scale 1, 3, 0.6, 3 ` set the scale
set terrain split 1, 16 ` split value by 16 * 16
set terrain tiling 1, 4 ` detail map tiling
set terrain light 1, 1, -0.25, 0, 1, 1, 0.78, 0.5 ` light - xdir, ydir, zdir, red, green, blue, intensity
set terrain texture 1, 1, 2 ` base and detail texture
build terrain 1 ` finally build the terrain
` load our skybox
load object "skybox2.x", 200
set object light 200, 0
set object texture 200, 3, 1
position object 200, 1000, 2000, 4000
scale object 200, 30000, 30000, 30000
` reset the directory
set dir ".."
` position the camera
position camera 385,23,100
`****************************************************************************
`****************************************************************************
`My culling chnages
`define constants for axi on testing auto_ellip sizes
#constant x_axis 1
#constant y_axis 2
#constant z_axis 3
`dim arrays for culling
dim frustum#(5,3)
dim clip#(15)
`gloabls for multiple objects
global maxLimbs = 0
global NumCullObjs = 0
`setup type for cull objs
type Cull_Obj_Data
Objnum as integer
Xpos as float
Ypos as float
Zpos as float
Cubesize as float
BoxXsize as float
BoxYsize as float
BoxZsize as float
Spheresize as float
endtype
dim Limb_Info(0, 0) as Cull_Obj_Data
`setup object 1 for culling
setup_Cull_obj( 1 )
`set default culling to Update terrain
cullmode = 0
`make vector for distance checks
ClipRange = 1
null=make vector3(1)
`****************************************************************************
`****************************************************************************
` main program loop
do
` handle user input and show some stats
gosub userInput
if cullmode = 0 then gosub information
` get the height of the terrain at the current camera position
a# = get terrain ground height( 1, camera position x( ), camera position z( ) )
` now position the camera slightly above the terrain
position camera camera position x( ), a# + 3, camera position z()
`****************************************************************************
`****************************************************************************
if keystate(2) = 1
cullmode = 1
endif
if keystate(3) = 1
cullmode = 2
endif
if keystate(4) = 1
cullmode = 3
endif
if keystate(11) = 1
cullmode = 0
endif
`cull if wanted
if cullmode > 0
resultcheck# = 0
gosub Extractfrustum
`check each object setup for culling
for j = 1 to NumCullObjs
`test each limb against the frustum (you would use an octree to cut down
`the cheks)
`CurrObj = Limb_Info(Limb_Info(j, 0).Objnum
for i = 0 to maxLimbs
select cullmode
case 1
resultcheck# = SphereInfrustum( Limb_Info(j, i).Xpos, Limb_Info(j, i).Ypos, Limb_Info(j, i).Zpos, Limb_Info(j, i).Spheresize )
if i = 0
print "Sphere auto culling"
endif
endcase
case 2
resultcheck# = CubeInfrustum( Limb_Info(j, i).Xpos, Limb_Info(j, i).Ypos, Limb_Info(j, i).Zpos, Limb_Info(j, i).Cubesize )
if i = 0
print "Cube auto culling"
endif
endcase
case 3
resultcheck# = BoxInfrustum( Limb_Info(j, i).Xpos, Limb_Info(j, i).Ypos, Limb_Info(j, i).Zpos, Limb_Info(j, i).BoxZsize, Limb_Info(j, i).BoxYsize, Limb_Info(j, i).BoxZsize )
if i = 0
print "Box auto culling"
endif
endcase
endselect
if resultcheck# > 0
if limb visible(Limb_Info(j, 0).Objnum,i) = 0
show limb 1, i
endif
else
if limb visible(Limb_Info(j, 0).Objnum,i) = 1
hide limb 1, i
endif
endif
next i
next j
else
` let the terrain handle some internal work
update terrain
print "Update terrain auto culling"
endif
`****************************************************************************
`****************************************************************************
` final screen update
sync
loop
`****************************************************************************
`****************************************************************************
null=delete matrix4(ProjectionMatrix)
null=delete matrix4(ViewMatrix)
null=delete matrix4(ClipMatrix)
null=delete vector3(ClipRange)
end
`****************************************************************************
`****************************************************************************
userInput:
` simple mouse and keyboard movement
` move around with arrow keys
control camera using arrowkeys 0, g_fSpeed#, g_fTurn#
` store old camera angle
OldCamAngleY# = CameraAngleY#
OldCamAngleX# = CameraAngleX#
` store new camera angle
CameraAngleY# = wrapvalue ( CameraAngleY# + mousemovex ( ) * 0.4 )
CameraAngleX# = wrapvalue ( CameraAngleX# + mousemovey ( ) * 0.4 )
` rotate camera
yrotate camera curveangle ( CameraAngleY#, OldCamAngleY#, 24 )
xrotate camera curveangle ( CameraAngleX#, OldCamAngleX#, 24 )
` speed up movement
if inkey$ ( ) = "+"
if g_fSpeed# < 1000
g_fSpeed# = g_fSpeed# + 0.01
endif
endif
` slow down movement
if inkey$ ( ) = "-"
if g_fSpeed# > 0.002
g_fSpeed# = g_fSpeed# - 0.001
endif
endif
return
information:
` show some information
` start printing at top of screen
set cursor 0, 0
` show frame rate
print "fps = " + str$ ( screen fps ( ) )
print "Press 0,1,2, or 3 key for differnt culling types."
` current camera position
print ""
print "x = " + str$ ( camera position x ( ) )
print "y = " + str$ ( camera position y ( ) )
print "z = " + str$ ( camera position z ( ) )
print ""
` finally the polygon count
print "polygon count = " + str$ ( statistic ( 1 ) )
print ""
return
`****************************************************************************
`****************************************************************************
Extractfrustum:
t# = 0
ProjectionMatrix = 1
ViewMatrix = 2
ClipMatrix = 3
null=MAKE MATRIX4(ProjectionMatrix)
null=MAKE MATRIX4(ViewMatrix)
null=MAKE MATRIX4(ClipMatrix)
`get the screen space matrix
Projection Matrix4 ProjectionMatrix
`get the camera space matrix
VIEW MATRIX4 ViewMatrix
`multiply the camera space matrix by the screen space matrix
`to get the clip matrix to get the frustum planes from
MULTIPLY MATRIX4 ClipMatrix, ViewMatrix, ProjectionMatrix
`assign the clip matrix elements to an array so we can use them
for i = 0 to 15
clip#(i) = DK Get Matrix4 Element( ClipMatrix, i )
next i
`/* Extract the numbers for the RIGHT plane */
frustum#(0,0) = clip#( 3) - clip#( 0);
frustum#(0,1) = clip#( 7) - clip#( 4);
frustum#(0,2) = clip#(11) - clip#( 8);
frustum#(0,3) = clip#(15) - clip#(12);
`/* Normalize the result */
rangeClipx# = frustum#(0,0)
rangeClipy# = frustum#(0,1)
rangeClipz# = frustum#(0,2)
set vector3 ClipRange, rangeClipx#, rangeClipy#, rangeClipz#
rangeClipresult#=length vector3(ClipRange)
t# = rangeClipresult#
frustum#(0,0) = frustum#(0,0) / t#
frustum#(0,1) = frustum#(0,1) / t#
frustum#(0,2) = frustum#(0,2) / t#
frustum#(0,3) = frustum#(0,3) / t#
`/* Extract the numbers for the LEFT plane */
frustum#(1,0) = clip#( 3) + clip#( 0);
frustum#(1,1) = clip#( 7) + clip#( 4);
frustum#(1,2) = clip#(11) + clip#( 8);
frustum#(1,3) = clip#(15) + clip#(12);
`/* Normalize the result */
`use distance from right plane to normalize data
frustum#(1,0) = frustum#(1,0) / t#
frustum#(1,1) = frustum#(1,1) / t#
frustum#(1,2) = frustum#(1,2) / t#
frustum#(1,3) = frustum#(1,3) / t#
`/* Extract the BOTTOM plane */
frustum#(2,0) = clip#( 3) + clip#( 1);
frustum#(2,1) = clip#( 7) + clip#( 5);
frustum#(2,2) = clip#(11) + clip#( 9);
frustum#(2,3) = clip#(15) + clip#(13);
`/* Normalize the result */
rangeClipx# = frustum#(2,0)
rangeClipy# = frustum#(2,1)
rangeClipz# = frustum#(2,2)
set vector3 ClipRange, rangeClipx#, rangeClipy#, rangeClipz#
rangeClipresult#=length vector3(ClipRange)
t# = rangeClipresult#
frustum#(2,0) = frustum#(2,0) / t#
frustum#(2,1) = frustum#(2,1) / t#
frustum#(2,2) = frustum#(2,2) / t#
frustum#(2,3) = frustum#(2,3) / t#
`/* Extract the TOP plane */
frustum#(3,0) = clip#( 3) - clip#( 1);
frustum#(3,1) = clip#( 7) - clip#( 5);
frustum#(3,2) = clip#(11) - clip#( 9);
frustum#(3,3) = clip#(15) - clip#(13);
`/* Normalize the result */
`use distance from bottom plane to normalize data
frustum#(3,0) = frustum#(3,0) / t#
frustum#(3,1) = frustum#(3,1) / t#
frustum#(3,2) = frustum#(3,2) / t#
frustum#(3,3) = frustum#(3,3) / t#
`/* Extract the FAR plane */
frustum#(4,0) = clip#( 3) - clip#( 2);
frustum#(4,1) = clip#( 7) - clip#( 6);
frustum#(4,2) = clip#(11) - clip#(10);
frustum#(4,3) = clip#(15) - clip#(14);
`/* Normalize the result */
rangeClipx# = frustum#(4,0)
rangeClipy# = frustum#(4,1)
rangeClipz# = frustum#(4,2)
set vector3 ClipRange, rangeClipx#, rangeClipy#, rangeClipz#
rangeClipresult#=length vector3(ClipRange)
t# = rangeClipresult#
frustum#(4,0) = frustum#(4,0) / t#
frustum#(4,1) = frustum#(4,1) / t#
frustum#(4,2) = frustum#(4,2) / t#
frustum#(4,3) = frustum#(4,3) / t#
`/* Extract the NEAR plane */
frustum#(5,0) = clip#( 3) + clip#( 2);
frustum#(5,1) = clip#( 7) + clip#( 6);
frustum#(5,2) = clip#(11) + clip#(10);
frustum#(5,3) = clip#(15) + clip#(14);
`/* Normalize the result */
rangeClipx# = frustum#(5,0)
rangeClipy# = frustum#(5,1)
rangeClipz# = frustum#(5,2)
set vector3 ClipRange, rangeClipx#, rangeClipy#, rangeClipz#
rangeClipresult#=length vector3(ClipRange)
t# = rangeClipresult#
frustum#(5,0) = frustum#(5,0) / t#
frustum#(5,1) = frustum#(5,1) / t#
frustum#(5,2) = frustum#(5,2) / t#
frustum#(5,3) = frustum#(5,3) / t#
return
function setup_Cull_obj( objnum as integer )
inc NumCullObjs, 1
perform checklist for object limbs 1
numterrlimbs = checklist quantity()
empty checklist
if numterrlimbs-1 > maxLimbs then maxLimbs = numterrlimbs-1
dim Limb_Info(NumCullObjs, maxLimbs) as Cull_Obj_Data
`store object numbers
Limb_Info(NumCullObjs, 0).Objnum = objnum
for i = 0 to numterrlimbs-1
make object from limb 99, 1, i
make mesh from object 99, 99
tempmaxx# = get_obj_max_vert( 99, x_axis )
tempmaxy# = get_obj_max_vert( 99, y_axis )
tempmaxz# = get_obj_max_vert( 99, z_axis )
tempminx# = get_obj_min_vert( 99, x_axis )
tempminy# = get_obj_min_vert( 99, y_axis )
tempminz# = get_obj_min_vert( 99, z_axis )
ellipsizex# = (tempmaxx# - tempminx#)/2
limb_max_size# = ellipsizex#
ellipsizey# = (tempmaxy# - tempminy#)/2
if ellipsizey# > limb_max_size# then limb_max_size# = ellipsizey#
ellipsizez# = (tempmaxz# - tempminz#)/2
if ellipsizez# > limb_max_size# then limb_max_size# = ellipsizez#
ellipposx# = tempminx# + ellipsizex#
ellipposy# = tempminy# + ellipsizey#
ellipposz# = tempminz# + ellipsizez#
delete mesh 99
delete object 99
`positions to use for all 3 types of testing
Limb_Info(NumCullObjs, i).Xpos = ellipposx#
Limb_Info(NumCullObjs, i).Ypos = ellipposy#
Limb_Info(NumCullObjs, i).Zpos = ellipposz#
`size to use for cube testing
Limb_Info(NumCullObjs, i).Cubesize = limb_max_size#*2.0
`sizes to use for box testing
Limb_Info(NumCullObjs, i).BoxXsize = ellipsizex#*2.0
Limb_Info(NumCullObjs, i).BoxYsize = ellipsizey#*2.0
Limb_Info(NumCullObjs, i).BoxZsize = ellipsizez#*2.0
`size to use for sphere testing
Limb_Info(NumCullObjs, i).Spheresize = sqrt((limb_max_size#*2.0)*(limb_max_size#*2.0) + (limb_max_size#*2.0)*(limb_max_size#*2.0))
next i
endfunction`distance from plane
`distance = A * X + B * Y + C * Z + D
function PointInfrustum( x#, y#, z# )
`check point against each plane of the frustum
for p = 0 to 5
`if behind any of them then exit
if (frustum#(p,0) * x#) + (frustum#(p,1) * y#) + (frustum#(p,2) * z#) + frustum#(p,3) <= 0
exitfunction 0
endif
next p
`if not behind any of them then it is inside and visible
endfunction 1
`returns 0 for outside and distance of sphere from camera if in
function SphereInfrustum( x#, y#, z#, radius# )
`set result to default
result# = 0
`check to see if the center point is within the radius of the sphere
`to the planes
for p = 0 to 5
d# = (frustum#(p,0) * x#) + (frustum#(p,1) * y#) + (frustum#(p,2) * z#) + frustum#(p,3)
`if not then it is out
if d# <= 0-radius#
exitfunction result#
endif
next p
`get the distange from the sphere to the camera if inside
`usefull for LOD calcs ;-)
result# = d# + radius#;
endfunction result#
function CubeInfrustum( x#, y#, z#, size# )
`test each point of the box against each plane
for p = 0 to 5
a = 0
if (frustum#(p,0) * (x# - size#)) + (frustum#(p,1) * (y# - size#)) + (frustum#(p,2) * (z# - size#)) + frustum#(p,3) > 0
a = 1
endif
if a = 0
if (frustum#(p,0) * (x# + size#)) + (frustum#(p,1) * (y# - size#)) + (frustum#(p,2) * (z# - size#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# - size#)) + (frustum#(p,1) * (y# + size#)) + (frustum#(p,2) * (z# - size#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# + size#)) + (frustum#(p,1) * (y# + size#)) + (frustum#(p,2) * (z# - size#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# - size#)) + (frustum#(p,1) * (y# - size#)) + (frustum#(p,2) * (z# + size#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# + size#)) + (frustum#(p,1) * (y# - size#)) + (frustum#(p,2) * (z# + size#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# - size#)) + (frustum#(p,1) * (y# + size#)) + (frustum#(p,2) * (z# + size#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# + size#)) + (frustum#(p,1) * (y# + size#)) + (frustum#(p,2) * (z# + size#)) + frustum#(p,3) > 0
a = 1
endif
endif
`if none of the points are in then exit test
if a = 0
exit
endif
next p
`if exited from none in give 0 as a result
if a = 0
exitfunction 0
endif
`else give a 1
endfunction 1
function BoxInfrustum( x#, y#, z#, sizex#, sizey#, sizez# )
for p = 0 to 5
a = 0
if (frustum#(p,0) * (x# - sizex#)) + (frustum#(p,1) * (y# - sizey#)) + (frustum#(p,2) * (z# - sizez#)) + frustum#(p,3) > 0
a = 1
endif
if a = 0
if (frustum#(p,0) * (x# + sizex#)) + (frustum#(p,1) * (y# - sizey#)) + (frustum#(p,2) * (z# - sizez#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# - sizex#)) + (frustum#(p,1) * (y# + sizey#)) + (frustum#(p,2) * (z# - sizez#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# + sizex#)) + (frustum#(p,1) * (y# + sizey#)) + (frustum#(p,2) * (z# - sizez#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# - sizex#)) + (frustum#(p,1) * (y# - sizey#)) + (frustum#(p,2) * (z# + sizez#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# + sizex#)) + (frustum#(p,1) * (y# - sizey#)) + (frustum#(p,2) * (z# + sizez#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# - sizex#)) + (frustum#(p,1) * (y# + sizey#)) + (frustum#(p,2) * (z# + sizez#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
if (frustum#(p,0) * (x# + sizex#)) + (frustum#(p,1) * (y# + sizey#)) + (frustum#(p,2) * (z# + sizez#)) + frustum#(p,3) > 0
a = 1
endif
endif
if a = 0
exit
endif
next p
if a = 0
exitfunction 0
endif
endfunction 1
`get the min vert position for an object axi are 1=x 2=y 3=z
function get_obj_min_vert( obj as integer, axis as integer )
`search through every limb's verts for the min positions to tell
`whick is the left, near, or bottom side
LOCK VERTEXDATA FOR MESH obj
for V=0 to GET VERTEXDATA VERTEX COUNT()-1
if V = 0
if axis = x_axis
_min#=GET VERTEXDATA POSITION X(V)
endif
if axis = y_axis
_min#=GET VERTEXDATA POSITION Y(V)
endif
if axis = z_axis
_min#=GET VERTEXDATA POSITION Z(V)
endif
else
if axis = x_axis
nmin#=GET VERTEXDATA POSITION X(V)
endif
if axis = y_axis
nmin#=GET VERTEXDATA POSITION Y(V)
endif
if axis = z_axis
nmin#=GET VERTEXDATA POSITION Z(V)
endif
if nmin# < _min# then _min# = nmin#
endif
next V
UNLOCK VERTEXDATA
endfunction _min#
`get the max vert position for an object axi are 1=x 2=y 3=z
function get_obj_max_vert( obj as integer, axis as integer )
`search through every limb's verts for the max positions to tell
`whick is the right, far, or top side
LOCK VERTEXDATA FOR MESH obj
for V=0 to GET VERTEXDATA VERTEX COUNT()-1
if V = 0
if axis = x_axis
_max#=GET VERTEXDATA POSITION X(V)
endif
if axis = y_axis
_max#=GET VERTEXDATA POSITION Y(V)
endif
if axis = z_axis
_max#=GET VERTEXDATA POSITION Z(V)
endif
else
if axis = x_axis
nmax#=GET VERTEXDATA POSITION X(V)
endif
if axis = y_axis
nmax#=GET VERTEXDATA POSITION Y(V)
endif
if axis = z_axis
nmax#=GET VERTEXDATA POSITION Z(V)
endif
if nmax# > _max# then _max# = nmax#
endif
next V
UNLOCK VERTEXDATA
endfunction _max#
`****************************************************************************
`****************************************************************************
And I know this is a feature request but it would be nice to have a function to actually get the matrix4 element values like this by Dmitry K:
float DK_Vectors_GetMatrixElement( int Matrix, int Element )
{
float res = 0.0;
D3DXMATRIX mat = dbGetMatrix(Matrix);
if (Element>=0 && Element<=15) res = mat[Element];
return res;
}
Instead of having to use a 3rd party plugin for such.
If nothing else it needs to be added to the help files that these commands are totally local.