## 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: 655
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 ) , klend 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: 3620
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 definesConst Pi = 4 * Atn(1)Dim Shared As Double TwoPi = 8 * Atn(1)Dim Shared As Double RtoD = 180 / Pi   ' radians * RtoD = degreesDim Shared As Double DtoR = Pi / 180   ' degrees * DtoR = radiansscreenres 500,500,32sub 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 subsub 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 subtype 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 typedim shared as LINE3D L3D(3) 'three linesfor i as integer = 0 to 2  'three lines    for j as integer = 0 to 1  'two points each        read L3D(i).x1(j)        read L3D(i).y1(j)        read L3D(i).z1(j)        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 jnext 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 rotationend subsub 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 subsub 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 subsub 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 iend subdim as double now1now1 = timer'rotate points around x,y axis center point 150,350dim as double angle'rotate around Z - AXISfor 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 = timernext angle'rotate around X - AXISfor 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 = timernext angle'rotate around Y - AXISfor 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 = timernext anglesleep'DATA BASE OF THREE LINESdata 0,100,0    'start point of linedata 0,-100,0   'end point of linedata -100,0,0data +100,0,0data 0,0,100data 0,0,-100`
Last edited by BasicCoder2 on Jun 21, 2015 13:12, edited 1 time in total.
MrSwiss
Posts: 3657
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: 3620
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) = 6items(1) = 4print 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 myTextmyText = "THIS IS A TEST STRING"printfor i as integer = 1 to len(myText)    print mid(myText,i,1);next iprintdim as any ptr ifor i as integer = 0 to len(myText)-1    print chr(myText[i]);next iprintsleep`

.
MrSwiss
Posts: 3657
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) = 6ReDim 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: 3620
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: 767
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: 10044
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 postdim as integer items(0)items(0) = 6items(1) = 4post = 1234print items(0),items(1)sleep`

Code: Select all

` 6             1234`
BasicCoder2
Posts: 3620
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 1items1(0) = 3items1(1) = 5print items1(0),items1(1)dim as integer post,items2(1 to 2)   'three locations even if only two are used?items2(0)=33post = 123     'see if this is the same locations as items2(0)items2(1) = 6items2(2) = 7print items2(0),items2(1),items2(2)sleep`
fxm
Posts: 10044
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 integerend typedim u as UDTu.items(0)=33u.post = 123     'see if this is the same locations as items(0)u.items(1) = 6u.items(2) = 7print u.items(0),u.items(1),u.items(2)sleep`

Code: Select all

` 123           6             7`
MrSwiss
Posts: 3657
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 ULongDim As ULong xzy(1) equals 2 x ULongDim 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 ULongDim As ULong xzy(0 To 1) equals 2 x ULongDim As ULong xzy(0 To 2) equals 3 x ULongthe same in BASIC-style BASE 1:Dim As ULong xzy(1 To 1) equals 1 x ULongDim As ULong xzy(1 To 2) equals 2 x ULongDim As ULong xzy(1 To 3) equals 3 x ULong`

Hope this clears the confusion ...
BasicCoder2
Posts: 3620
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: 10044
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.