Hi guys,
if you are a little familiar with memblocks and creating 3D objects from them, you know that it's not as easy as it looks.
You have to worry about memblock size, FVF format, offset calculation, normals and so on.
The advanced folks may laugh at that, but for beginners it costs a lot of nerves and mostly
code.
Is there an easier way?
Ok, lets start.
First of all you need my header - Venom_v1.0.dba
You can get it from the code snippet below or by downloading the attached file.
#constant true 1
#constant false 0
#constant DBP_NORMAL 0
#constant VENOM_NORMAL 1
type memblockObjectType
mesh as integer
image as integer
object as integer
memblock as integer
endtype
type vertexDataType
pos_x as float
pos_y as float
pos_z as float
normal_x as float
normal_y as float
normal_z as float
diffuse as dword
u as float
v as float
endtype
function venomStart()
global this as memblockObjectType
global busy as boolean : busy = false
global dim vertices() as vertexDataType
global vertexIndex as integer : vertexIndex = -1
global useNormal as integer : useNormal = VENOM_NORMAL
global vertex_count as integer : vertex_count = 0
global vertexDefaultColor as dword : vertexDefaultColor = 0xFFFFFF
endfunction
function venomEnd()
undim vertices()
endfunction
function begin_object(obj_id)
if (object exist(obj_id) = false and busy = false)
busy = true
this.object = obj_id
this.mesh = find free mesh()
this.memblock = find free memblock()
endif
endfunction
function end_object()
busy = false
vertex_count = get array size(vertices())
if (vertex_count > 2)
vertex_count = 3*int(floor(vertex_count/3.0))
make memblock this.memblock, 12+(36*vertex_count)
write memblock dword this.memblock, 0, 338
write memblock dword this.memblock, 4, 36
write memblock dword this.memblock, 8, vertex_count
if (useNormal = VENOM_NORMAL) then venomNormaliseObject()
for n = 0 to vertex_count - 1
write memblock float this.memblock, n*36+12, vertices(n).pos_x
write memblock float this.memblock, n*36+16, vertices(n).pos_y
write memblock float this.memblock, n*36+20, vertices(n).pos_z
write memblock float this.memblock, n*36+24, vertices(n).normal_x
write memblock float this.memblock, n*36+28, vertices(n).normal_y
write memblock float this.memblock, n*36+32, vertices(n).normal_z
write memblock dword this.memblock, n*36+36, vertices(n).diffuse
write memblock float this.memblock, n*36+40, vertices(n).u
write memblock float this.memblock, n*36+44, vertices(n).v
next n
make mesh from memblock this.mesh, this.memblock
make object this.object, this.mesh, this.image
if (useNormal = DBP_NORMAL) then set object normals this.object
endif
vertexIndex = -1
empty array vertices()
if mesh exist(this.mesh) then delete mesh this.mesh
if memblock exist(this.memblock) then delete memblock this.memblock
endfunction
function vertex(x#, y#, z#)
if (busy)
array insert at bottom vertices()
vertices().pos_x = x#
vertices().pos_y = y#
vertices().pos_z = z#
vertices().normal_x = 0
vertices().normal_y = 0
vertices().normal_z = 0
vertices().diffuse = vertexDefaultColor
vertices().u = 0
vertices().v = 0
inc vertexIndex
endif
endfunction
function uv(u#, v#)
if (vertexIndex > -1 and busy = true)
vertices().u = u#
vertices().v = v#
endif
endfunction
function color(myColor as dword)
if (vertexIndex > -1 and busy = true)
vertices().diffuse = myColor
endif
endfunction
function color_def(myColor as dword)
vertexDefaultColor = myColor
endfunction
function color_rand()
if (vertexIndex > -1 and busy = true)
vertices().diffuse = rgb(rnd(255),rnd(255),rnd(255))
endif
endfunction
function dual_face()
if (vertexIndex >= 2 and busy = true)
for j = 0 to 2
array insert at bottom vertices()
vertices() = vertices(vertexIndex-j)
next j
inc vertexIndex, 3
endif
endfunction
function flip_face()
if (vertexIndex >= 2 and busy = true)
temp as vertexDataType
temp = vertices(vertexIndex-2) `temp = 1
vertices(vertexIndex-2) = vertices(vertexIndex) `1 = 3
vertices(vertexIndex) = temp `3 = 1
endif
endfunction
function venomNormaliseObject()
r = make vector3(1)
r = make vector3(2)
r = make vector3(3)
r = make vector3(4)
r = make vector3(5)
r = make vector3(6)
r = make vector3(7)
for indice = 0 to (vertex_count-1) step 3
set vector3 1, vertices(indice+0).pos_x, vertices(indice+0).pos_y, vertices(indice+0).pos_z
set vector3 2, vertices(indice+1).pos_x, vertices(indice+1).pos_y, vertices(indice+1).pos_z
set vector3 3, vertices(indice+2).pos_x, vertices(indice+2).pos_y, vertices(indice+2).pos_z
subtract vector3 4, 2, 1
subtract vector3 5, 3, 1
cross product vector3 6, 4, 5
normalize vector3 7, 6
x# = x vector3(7)
y# = y vector3(7)
z# = z vector3(7)
vertices(indice+0).normal_x = x#
vertices(indice+0).normal_y = y#
vertices(indice+0).normal_z = z#
vertices(indice+1).normal_x = x#
vertices(indice+1).normal_y = y#
vertices(indice+1).normal_z = z#
vertices(indice+2).normal_x = x#
vertices(indice+2).normal_y = y#
vertices(indice+2).normal_z = z#
next indice
r = delete vector3(1)
r = delete vector3(2)
r = delete vector3(3)
r = delete vector3(4)
r = delete vector3(5)
r = delete vector3(6)
r = delete vector3(7)
endfunction
function venomTileXZ(x#, y#, z#, size)
vertex(x#,y#,z#)
vertex(x#,y#,z#+size)
vertex(x#+size,y#,z#+size)
vertex(x#,y#,z#)
vertex(x#+size,y#,z#+size)
vertex(x#+size,y#,z#)
endfunction
function venomTileXY(x#, y#, z#, size)
vertex(x#,y#,z#)
vertex(x#,y#+size,z#)
vertex(x#+size,y#,z#)
vertex(x#,y#+size,z#)
vertex(x#+size,y#+size,z#)
vertex(x#+size,y#,z#)
endfunction
function venomTileYZ(x#, y#, z#, size)
vertex(x#,y#,z#)
vertex(x#,y#,z#+size)
vertex(x#,y#+size,z#+size)
vertex(x#,y#,z#)
vertex(x#,y#+size,z#+size)
vertex(x#,y#+size,z#)
endfunction
function dual_tile()
if (vertexIndex >= 5 and busy = true)
for j = 0 to 5
array insert at bottom vertices()
vertices() = vertices(vertexIndex-j)
next j
inc vertexIndex, 6
endif
endfunction
function flip_tile()
if (vertexIndex >= 5 and busy = true)
temp as vertexDataType
temp = vertices(vertexIndex-5)
vertices(vertexIndex-5) = vertices(vertexIndex-3)
vertices(vertexIndex-3) = temp
temp = vertices(vertexIndex-2)
vertices(vertexIndex-2) = vertices(vertexIndex)
vertices(vertexIndex) = temp
endif
endfunction
Now start a new project and import the header.
Solution Explorer -> Import Existing File -> Venom_v1.0.dba
The basic template for Venom looks like that:
sync on : sync rate 0
venomStart()
//code
.
.
.
venomEnd()
To see the actual results we'll use the more advanced one shown below:
// Venom template
sync on
sync rate 0
autocam off
disable escapekey
venomStart()
make matrix 1, 1, 1, 5, 5
position matrix 1, 0, 0, 0
make light 1
position camera 0, 0, 0.5, 0
// create your objects here
begin_object(1)
vertex(1,0,0) // 3 vertices = 1 face
vertex(0,1,0)
vertex(0,0,1)
`etc.
end_object()
do
text 0, 0, str$(screen fps())
control camera using arrowkeys 0, 0.05, 0.5
position light 1, camera position x(0), camera position y(0), camera position z(0)
if spacekey() = 1 then exit
sync
loop
venomEnd()
end
Now compile and run the project. Use arrowkeys to navigate around the matrix until you see the white triangle.
To draw a mesh in the 3D world we use vertices.
In our case, we made the simplest mesh - triangle.
3 vertices form 1 triangle
Now look at the template and find the section:
begin_object(n)
vertex(x1#, y1#, z1#) 3 fertices = 1 face
vertex(x2#, y2#, y2#)
vertex(x3#, y3#, z3#)
`etc.
end_object()
Thats the place where the magic happens
To create object with Venom, you have to type
begin_object(n), where n is the object number.
By definition n must be greater than 0.
Then just type the vertices you want(probably you'll need a little imagination).
As you'll see the order in which you declare your vertices counts.
But I'll explain that in other post.
You can create more complex objects using triangles.
But
you can't type 4 vertices and expect to get quad,
because DBPro doesn't support that.
But there is solution to that I'll show you at the end.
-Why the triangle is visible only from one side?
Because 3 vertices form only one face. To be visible from both sides you need to add another 3 vertices in reversed order or just type
dual_face() after the last one like this:
begin_object(1)
vertex(1,0,0)
vertex(0,1,0)
vertex(1,0,1)
dual_face()
-Can I change the color of the vertices?
Yes, you can. You can use
color_def(myColor as dword) to set default color for all vertices or use color(myColor as dword) after each one
begin_object(1)
vertex(1,0,0)
color(rgb(255,0,0))
vertex(0,1,0)
color(rgb(0,255,0))
vertex(1,0,1)
color(rgb(0,0,255))
dual_face()
In addition you can use
color_rand() for random color.
To flip a face just type
flip_face():
begin_object(1)
vertex(1,0,0)
vertex(0,1,0)
vertex(1,0,1)
flip_face()
You can set uv values using uv(u#, v#) after each vertex. By default all are set to (0, 0).
Normals are calculated automatically after end_object() is reached.
You don't need to worry about them.
The limits of Venom:
- only one object at a time(you cant cycle begin_object() in another one).
But
you can do this:
begin_object(1)
.
.
.
end_object()
begin_object(2)
.
.
.
end_object()
To simulate quads you can use the following commands:
venomTileXZ(x#, y#, z#, size)
venomTileXY(x#, y#, z#, size)
venomTileYZ(x#, y#, z#, size)
in combo with:
flip_tile()
dual_tile()
With their help you can make terrains, but at the moment they have limited usage.
But nothing stops you to implement your own functions.
That from me for now...
begin_object(1)
for n = 0 to 100
color_def(rgb(rnd(255),rnd(255),rnd(255)))
vertex(rnd(20),rnd(20),rnd(20))
vertex(rnd(20),rnd(20),rnd(20))
vertex(rnd(20),rnd(20),rnd(20))
next n
end_object()
Bye!