## Simple 3D model

Game development specific discussions.
Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Simple 3D model

This is my first attempt at 3D. It doesn't work because the lines radius's don't shrink correctly.
I'd be happy if someone could show me how to get it working.

[code=vb file=Untitled.bas]

Const Pi = 4 * Atn(1)
Dim Shared As Double TwoPi = 8 * Atn(1)
Dim Shared As Double RtoD = 180 / Pi
Dim Shared As Double DtoR = Pi / 180

screenres 640,480,32

cx = 320
cy = 240

anglex=90
angley=0
anglez=90

do

if anglex=180 then anglex=0
if anglex=-180 then anglex=0
if angley=180 then angley=0
if angley=-180 then angley=0
if anglez=180 then anglez=0
if anglez=-180 then anglez=0
screenlock
cls

line (cx-xdx,cy-xdy)-(xdx+cx,xdy+cy),rgb(0,255,0)
line (cx-ydx,cy-ydy)-(ydx+cx,ydy+cy),rgb(0,255,0)
line (cx-zdx,cy-zdy)-(zdx+cx,zdy+cy),rgb(0,255,0)

paint (4, 478),rgb(0,255,0), rgb(0,0,0)
IF MULTIKEY(&h4B) THEN anglex=anglex-1:angley=angley-1':anglez=anglez-1
IF MULTIKEY(&h4D) THEN anglex=anglex+1:angley=angley+1':anglez=anglez+1

print "angle y "+str(angley)
print "angle x "+str(anglex)
print "angle z "+str(anglez)

screenunlock
sleep 10, 1
loop until multikey(&H01)

[/code]
bluatigro
Posts: 651
Joined: Apr 25, 2012 10:35
Location: netherlands

### Re: Simple 3D model

try this :

Code: Select all

sub lijn( x1 as single , y1 as single , z1 as single _
, x2 as single , y2 as single , z2 as single , kl as integer )
if z1 < -900 or z2 < -900 then exit sub
dim as single a1 , b1 , a2 , b2
a1 = winx / 2 + x1 / ( z1 + 1000 ) * 1000
b1 = winy / 2 - y1 / ( z1 + 1000 ) * 1000
a2 = winx / 2 + x2 / ( z2 + 1000 ) * 1000
b2 = winy / 2 - y2 / ( z2 + 1000 ) * 1000
line ( a1 , b1 ) - ( a2 , b2 ) , kl
end sub

winx and winy are the size of the screen in pixels

see sky car 3d [ line version ] on the ful how to use code
BasicCoder2
Posts: 3576
Joined: Jan 01, 2009 7:03
Location: Australia

### Re: Simple 3D model

Boromir wrote:I'd be happy if someone could show me how to get it working.

I wouldn't have a clue how to "get it working" as I think you are going about it the wrong way.

Don't think in terms of lines think in terms of points in 3D space.

Thus in the example below set(x,y) becomes set3D(x,y,z) and line(x1,y1)-(x2,y2) becomes drawLine3D(x1,y1,z1,x2,y2,z2)

These routines are one way to project the 3D points onto a 2D screen.

You will find some examples here on how to do simple 3D graphics,
http://www.petesqbsite.com/sections/tut ... hics.shtml

Below I have modified a rotating cube demo to handle just the three lines of an x,y,z axis.

Code: Select all

'SCREEN VIEW
'             -Y      +Z
'              |     /
'              |    /
'              |   /
'              |  /
'              | /
'              |/
' - X ---------o----------> +X
'             /|
'            / |
'           /  |
'          /   |
'         /    |
'        /     |
'      -Z      |
'             +Y
'
'
'some useful defines
Const Pi = 4 * Atn(1)
Dim Shared As Double TwoPi = 8 * Atn(1)
Dim Shared As Double RtoD = 180 / Pi   ' radians * RtoD = degrees
Dim Shared As Double DtoR = Pi / 180   ' degrees * DtoR = radians

screenres 500,500,32

sub set3D(x as double,y as double,z as double)
circle (x+z\2+250,y-z\2+250),3,rgb(0,255,0)
draw string (x+z\2+250,y-z\2+250),str(int(x+.5))+","+str(int(y+.5))+","+str(int(z+.5))
end sub

sub drawLine3D(x1 as double,y1 as double,z1 as double,x2 as double,y2 as double,z2 as double)
line (x1+z1\2+250,y1-z1\2+250)-(x2+z2\2+250,y2-z2\2+250),rgb(255,0,0)
set3D(x1,y1,z1)
set3D(x2,y2,z2)
end sub

type LINE3D
as double  x1(2)  'two points to a line
as double  y1(2)
as double  z1(2)
as double rx1(2)
as double ry1(2)
as double rz1(2)
end type

dim shared as LINE3D L3D(3) 'three lines

for i as integer = 0 to 2  'three lines
for j as integer = 0 to 1  'two points each
L3D(i).rx1(j) = L3D(i).x1(j)
L3D(i).ry1(j) = L3D(i).y1(j)
L3D(i).rz1(j) = L3D(i).z1(j)
next j
next i

sub rotatePointsZ(angle as double)
dim as double px1,py1,pz1
for i as integer = 0 to 2  ' three lines
for j as integer = 0 to 1  ' two points each
px1 = L3D(i).x1(j)
py1 = L3D(i).y1(j)
pz1 = L3D(i).z1(j)
L3D(i).rx1(j) = (Cos(angle*DtoR) * px1 - Sin(angle*DtoR) * py1)
L3D(i).ry1(j) = (Sin(angle*DtoR) * px1 + Cos(angle*DtoR) * py1)
next j
next i
set3D(0,0,0) 'center of rotation
end sub

sub rotatePointsX(angle as double)
dim as double px1,py1,pz1
for i as integer = 0 to 2  ' three lines
for j as integer = 0 to 1  ' two points each
pz1 = L3D(i).z1(j)
py1 = L3D(i).y1(j)
px1 = L3D(i).x1(j)
L3D(i).rz1(j) = (Cos(angle*DtoR) * pz1 - Sin(angle*DtoR) * py1)
L3D(i).ry1(j) = (Sin(angle*DtoR) * pz1 + Cos(angle*DtoR) * py1)
next j
next i
set3D(0,0,0)
end sub

sub rotatePointsY(angle as double)
dim as double px1,py1,pz1
for i as integer = 0 to 2  ' three lines
for j as integer = 0 to 1  'two points each
pz1 = L3D(i).z1(j)
px1 = L3D(i).x1(j)
py1 = L3D(i).y1(j)
L3D(i).rz1(j) = (Cos(angle*DtoR) * pz1 - Sin(angle*DtoR) * px1)
L3D(i).rx1(j) = (Sin(angle*DtoR) * pz1 + Cos(angle*DtoR) * px1)
next j
next i
set3D(0,0,0)
end sub

sub drawPolygons()
for i as integer = 0 to 2  'three lines
drawLine3D(L3D(i).rx1(0), L3D(i).ry1(0), L3D(i).rz1(0),  L3D(i).rx1(1) ,L3D(i).ry1(1) ,L3D(i).rz1(1) )
next i
end sub

dim as double now1
now1 = timer
'rotate points around x,y axis center point 150,350
dim as double angle

'rotate around Z - AXIS
for angle = 0 to 360 step 10
cls
locate 2,2
print "ANGLE ROTATION AROUND Z-AXIS =";angle
rotatePointsZ(angle)
drawPolygons()
while timer-now1 < 0.1
sleep 2
wend
now1 = timer
next angle

'rotate around X - AXIS
for angle = 0 to 360 step 10
cls
locate 2,2
print "ANGLE ROTATION AROUND X-AXIS =";angle
rotatePointsX(angle)
drawPolygons()
while timer-now1 < 0.1
sleep 2
wend
now1 = timer
next angle

'rotate around Y - AXIS
for angle = 0 to 360 step 10
cls
locate 2,2
print "ANGLE ROTATION AROUND Y-AXIS =";angle
rotatePointsY(angle)
drawPolygons()
while timer-now1 < 0.1
sleep 2
wend
now1 = timer
next angle

sleep

'DATA BASE OF THREE LINES
data 0,100,0    'start point of line
data 0,-100,0   'end point of line
data -100,0,0
data +100,0,0
data 0,0,100
data 0,0,-100
Last edited by BasicCoder2 on Jun 21, 2015 13:12, edited 1 time in total.
MrSwiss
Posts: 3577
Joined: Jun 02, 2013 9:27
Location: Switzerland

### Re: Simple 3D model

@BasicCoder2,
Just a hint:
the use of C-style definition of arrays is BASE 0 (zero), so your array (below) holds 3 Doubles (points) to a line ...
x1(0), x1(1) and x1(2) ... it is better to use BASIC- style definition like x1(1 to 2) or x1(0 to 1) to get what you want.

The same applies to Dim Shared As LINE3D L3D() array dimensions ...

You won't get any errors this way but it's a waste of resources to have arrays "larger than needed".
BasicCoder2 wrote:type LINE3D
as double x1(2) 'two points to a line
as double y1(2)
as double z1(2)
as double rx1(2)
as double ry1(2)
as double rz1(2)
end type

dim shared as LINE3D L3D(3) 'three lines

Let me add a simple calculation:
your L3D(3) array holds (for each defined Double in Type) 3 * 4 Doubles = 12 Doubles, instead of the 2 * 3 = 6 Doubles you'd expect ...
this equals to: "50% of allocated memory is for nothing".
BasicCoder2
Posts: 3576
Joined: Jan 01, 2009 7:03
Location: Australia

### Re: Simple 3D model

@MrSwiss,
Yes this was pointed out to me once before. For me it is an ingrained way of thinking. Physically an address (or index to the first item from an address) is zero not one. That is how it is in the computer hardware and how it is with machine code instructions no matter how it is represented at a "higher level". I assume then that dim as integer (1 to 2) still physically stores the first item at index = 0 and the second item at index = 1 and thus a subtraction of one is required before the compiler generates the actual machine code that everything must ultimately reduces to.

I could just write my array declarations as,

Code: Select all

dim as integer items(0)
items(0) = 6
items(1) = 4
print items(0),items(1)
sleep

However I do take on board what you say and have used the items(1 to 2) declaration which sometimes can make the code more readable, particularly for those unaware of how it all works at a lower level and are used to numbering items 1 to n.

FreeBasic does have C ways as well. Same action, print a string array, two ways to address the items.

Code: Select all

dim as string myText
myText = "THIS IS A TEST STRING"
print
for i as integer = 1 to len(myText)
print mid(myText,i,1);
next i
print
dim as any ptr i
for i as integer = 0 to len(myText)-1
print chr(myText[i]);
next i
print
sleep

.
MrSwiss
Posts: 3577
Joined: Jun 02, 2013 9:27
Location: Switzerland

### Re: Simple 3D model

@BasicCode2,
your example code won't work, because you'd blow the array (upper) bound:
BasicCoder2 wrote:I could just write my array declarations as,

Code:

Code: Select all

dim as integer items(0)
items(0) = 6
items(1) = 4    ' <-- this will throw a compiler error
print items(0),items(1)
sleep

You'd have to do a ReDim of items array before that will work:

Code: Select all

dim as integer items(0)
items(0) = 6
ReDim Preserve items(1)    ' or ReDim Preserve items(0 to 1)
' without the additional 'preserve' you'd loose the items(0) preset value ...
items(1) = 4
print "" & items(0) & " " & items(1)
sleep : end

another way would be:

Code: Select all

Dim as integer items()    ' uninitialised, unsized array
Redim items(1)    ' now size it to hold 2 integers
...
sleep : end
BasicCoder2
Posts: 3576
Joined: Jan 01, 2009 7:03
Location: Australia

### Re: Simple 3D model

MrSwiss wrote:@BasicCode2,your example code won't work, because you'd blow the array (upper) bound:

I did run it before posting and it seemed to work ok. There was no compiler error.
.
grindstone
Posts: 744
Joined: May 05, 2015 5:35
Location: Germany

### Re: Simple 3D model

There really is no compiler error, but I strongly recommend NOT to access an array beyond its defined boundaries, for this could have the same side effects as accessing an unallocated memory area by a pointer.

Regards
grindstone
fxm
Posts: 9828
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Simple 3D model

Yes, because dangerous!
That code compiles without option '-exx', but attention to the result:

Code: Select all

dim as integer post
dim as integer items(0)
items(0) = 6
items(1) = 4
post = 1234
print items(0),items(1)
sleep

Code: Select all

6             1234
BasicCoder2
Posts: 3576
Joined: Jan 01, 2009 7:03
Location: Australia

### Re: Simple 3D model

I am just confused as to how the declarations are being translated. I assumed that dim as integer items(1 to 2) only assigned two locations but there appears to be a zero location as well?
So if I use dim as integer items(1 to 2) the reality is three locations are assigned so the first location goes to waste?
Whereas if I used dim as integer items(2) then only two locations are assigned.

Code: Select all

dim as integer items1(2)   'locations 0 to 1
items1(0) = 3
items1(1) = 5
print items1(0),items1(1)

dim as integer post,items2(1 to 2)   'three locations even if only two are used?
items2(0)=33
post = 123     'see if this is the same locations as items2(0)
items2(1) = 6
items2(2) = 7
print items2(0),items2(1),items2(2)

sleep
fxm
Posts: 9828
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Simple 3D model

No.

dim as integer items1(2)
is equivalent to:
dim as integer items1(0 to 2)
and allocates 3 integers (items1(0), items1(1) and items1(2))

dim as integer items2(1 to 2)
allocates only 2 integers (items2(1) and items2(2))

Example (always compiling without option '-exx'):

Code: Select all

type UDT
post as integer
items(1 to 2) as integer
end type

dim u as UDT
u.items(0)=33
u.post = 123     'see if this is the same locations as items(0)
u.items(1) = 6
u.items(2) = 7
print u.items(0),u.items(1),u.items(2)
sleep

Code: Select all

123           6             7
MrSwiss
Posts: 3577
Joined: Jun 02, 2013 9:27
Location: Switzerland

### Re: Simple 3D model

BasicCoder2 wrote:I am just confused as to how the declarations are being translated. I assumed that dim as integer items(1 to 2) only assigned two locations but there appears to be a zero location as well?

You are still confusing BASIC-/C-style array dimensioning:

Code: Select all

In C-style, always BASE 0:    ' you are only specifying the upper bound of the array, lower bound is implicitly 0
Dim As ULong xzy(0) equals 1 x ULong
Dim As ULong xzy(1) equals 2 x ULong
Dim As ULong xzy(2) equals 3 x ULong
...
the same in BASIC-style BASE 0:
Dim As ULong xzy(0 To 0) equals 1 x ULong
Dim As ULong xzy(0 To 1) equals 2 x ULong
Dim As ULong xzy(0 To 2) equals 3 x ULong
the same in BASIC-style BASE 1:
Dim As ULong xzy(1 To 1) equals 1 x ULong
Dim As ULong xzy(1 To 2) equals 2 x ULong
Dim As ULong xzy(1 To 3) equals 3 x ULong

Hope this clears the confusion ...
BasicCoder2
Posts: 3576
Joined: Jan 01, 2009 7:03
Location: Australia

### Re: Simple 3D model

@fxm and MrSwiss,
Thanks for clearing that up.
Clearly I have been misunderstanding the nomenclature when declaring the dimensions of a BASIC array.
In future I will have to think of dim as integer array(n) as dim as integer array(0 to n)
I checked with my old MS-DOS QBASIC manual and indeed that is how it has always been.
Back in my old MS-DOS days I mostly coded in Assembler and then later in C.
The reason I converted to FreeBASIC was for readability compared with C and FreeBASIC's easy to use graphics.
In the old days it was easy enough to program the graphic card directly compared with the modern hardware that comes with an overlay of complex software.
.
fxm
Posts: 9828
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Simple 3D model

'Option Base N' exists always in FreeBASIC, but is only supported in the -lang fblite and -lang qb dialects.