First steps in GLB 3D

Previous topic - Next topic

Ian Price

Whilst I have been a strictly 2D guy with GLB, I have played around with very basic 3D in the past (in Blitz3D). However I now want to have a go with 3D in GLB, and I'm already stuck on something simple! Rotating a 3D ball - what could be simpler? I can display the ball, with a texture, but the rotation is buggered up.

Code (glbasic) Select

SETSCREEN 640,480,0

GLOBAL scale#=3.0, x, y, z, phi

// Create sphere
CreateSphere(1,30,20,RGB(255,255,255))

// Draw rects (used as sphere texture)
FOR n=0 TO 2000
DRAWRECT RND(256),RND(256),RND(32),RND(32),RGB(RND(255),RND(255),RND(255))
NEXT

// Grab sprite to use as sphere texture
GRABSPRITE 1,0,0,256,256

// Repeat until ESC pressed
WHILE TRUE

X_MAKE3D 1,1000,45
X_CAMERA 0, 20, 900, 0, 0, 0

X_SCALING scale, scale, scale

// Rotate ball
IF KEY(200) AND move=0
  dir=-1
  x=1
  y=0
  move=45
ENDIF

IF KEY(208) AND move=0
  dir=1
  x=1
  y=0
  move=45
ENDIF

IF KEY(203) AND move=0
  dir=-1
  y=1
  x=0
  move=45
ENDIF

IF KEY(205) AND move=0
  dir=1
  y=1
  x=0
  move=45
ENDIF

IF move>0
  INC phi, dir*2
  DEC move
ENDIF

X_ROTATION phi,x,y,z

X_SETTEXTURE 1,-1
X_DRAWOBJ 1, 0

SHOWSCREEN

WEND


// Create primitive
FUNCTION CreateSphere: num, r, n, col
LOCAL i,j, theta1, theta2, theta3, pi
pi = ACOS(0)*2
IF r < 0 THEN r = -r
IF n < 4 THEN n = 4

X_OBJSTART num
FOR j=0 TO INTEGER(n/2) -1
theta1 = j * 2*pi / n - pi/2;
theta2 = (j + 1) * 2*pi / n - pi/2;
FOR i=0 TO n
theta3 = i * 2*pi / n;
X_OBJADDVERTEX r*COS(theta2) * COS(theta3), r*SIN(theta2), _
r*COS(theta2) * SIN(theta3), i/n, 2*(j+1)/n, col
X_OBJADDVERTEX r*COS(theta1) * COS(theta3), r*SIN(theta1), _
r*COS(theta1) * SIN(theta3), i/n, 2*j/n, col
NEXT
X_OBJNEWGROUP
NEXT
X_OBJEND
ENDFUNCTION


I can rotate the sphere with the cursors, however if you change direction, sometimes the sphere's texture/sphere's orientation "jumps." It's OK in any orientation UP/DOWN or LEFT/RIGHT, however if you press UP then RIGHT you'll see what I mean.

Can anybody give me a prod in the right direction - remember I'm strictly 2D and even the 3D commands here are essntially new to me.

Cheers :)
I came. I saw. I played.

matchy

This is not a texture map issue because you couldn't else know which way the sphere is with even facets.  :P

In the sample code, the alternative object axis are being reset zero instead the last angle. I noticed removing x=0 and y=0 twice to see that the texture remains intact on the second turn.

Ian Price

#2
But removingX=0/Y=0 doesn't stop the problem (you would have  seen if you continued changing directions) - and it also allows the sphere/texture to turn at non-90degree angles, which I don't want.

I want the sphere/texture to ONLY rotate in the four main compass directions - N,S,E,W.

I need this to work for more than two turns/revolutions/button presses.

In fact - pressing just UP and then LEFT causes the same problem i mention even if you do remove X=0 / Y=0.
I came. I saw. I played.

bigsofty

Its to do with the way you are applying 'phi', your rotating along an axis by 'phi' degrees(storing phi as you go), which is fine, but when you change to another axis you are applying you horizontal change(phi) directly to the vertical change suddenly. You need to store phiX and phiY, when you need to rotate the objects axis on the x and y plane. Two axis require to vars to store them in.
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Crivens

I did this about 10 years ago in Dark Basic (Trailblazer clone). I posted an almost identical post and a bloke called Dr Avalanche (believe he went to Blitz) sorted me out with the code. Might be lucky and still have a copy at home...

Cheers
Current fave quote: Cause you like musicians and I like people with boobs.

bigsofty

#5
Remember since you have only one input, really X_ROTATION is only usable on one axis...

Code (glbasic) Select
X_ROTATION phiX, 1, 0, 0
X_ROTATION phiY, 0, 1, 0


So I rotate the X axis by phiX, followed by the Y axis using phiY. You need two consecutive commands. (X_MULTMATRIX is a better solution as multiple transformations can performed in one command)
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

matchy

Just to note, X_ROTATION is for translating the objects and X_SETTEXTUREOFFSET is for translating the texture.  :rtfm:

bigsofty

OK, here a modified version of your code...

Code (glbasic) Select
// --------------------------------- //
// Project: test2
// Start: Wednesday, November 24, 2010
// IDE Version: 8.148


// SETCURRENTDIR("Media") // seperate media and binaries?

SETSCREEN 640,480,0

GLOBAL scale#=3.0, x#, y#, z#, phiX#, phiY

// Create sphere
CreateSphere(1,30,20,RGB(255,255,255))

// Draw rects (used as sphere texture)
FOR n=0 TO 2000
DRAWRECT RND(256),RND(256),RND(32),RND(32),RGB(RND(255),RND(255),RND(255))
NEXT

// Grab sprite to use as sphere texture
GRABSPRITE 1,0,0,256,256


// Repeat until ESC pressed
WHILE TRUE



// Rotate ball
IF KEY(200) AND move=0
  dir=-1
  x=1
  y=0
  move=45
ENDIF

IF KEY(208) AND move=0
  dir=1
  x=1
  y=0
  move=45
ENDIF

IF KEY(203) AND move=0
  dir=-1
  y=1
  x=0
  move=45
ENDIF

IF KEY(205) AND move=0
  dir=1
  y=1
  x=0
  move=45
ENDIF

IF move>0
  IF x>0 THEN phiX = phiX + dir*2
  IF y>0 THEN phiY = phiY + dir*2
   DEC move
ENDIF

X_MAKE3D 1,1000,45
X_CAMERA 0, 20, 900, 0, 0, 0
X_SCALING scale, scale, scale


X_SETTEXTURE 1, -1
X_ROTATION phiX, 1, 0, 0
X_ROTATION phiY, 0, 1, 0

X_DRAWOBJ 1, 0

SHOWSCREEN

WEND


// Create primitive
FUNCTION CreateSphere: num, r, n, col
LOCAL i,j, theta1, theta2, theta3, pi
pi = ACOS(0)*2
IF r < 0 THEN r = -r
IF n < 4 THEN n = 4

X_OBJSTART num
FOR j=0 TO INTEGER(n/2) -1
theta1 = j * 2*pi / n - pi/2;
theta2 = (j + 1) * 2*pi / n - pi/2;
FOR i=0 TO n
theta3 = i * 2*pi / n;
X_OBJADDVERTEX r*COS(theta2) * COS(theta3), r*SIN(theta2), _
r*COS(theta2) * SIN(theta3), i/n, 2*(j+1)/n, col
X_OBJADDVERTEX r*COS(theta1) * COS(theta3), r*SIN(theta1), _
r*COS(theta1) * SIN(theta3), i/n, 2*j/n, col
NEXT
X_OBJNEWGROUP
NEXT
X_OBJEND
ENDFUNCTION


Now if you run this, you might think, well that's kinda bonkers! But have think what its doing. Its rotating the axis of the obect then apply another rotate to the another axis directly afterwards. Think of the sphere as a little man's head, you tell him to turn to the left, then look up and then down, turn again, look up and then down...

As I said, using matrices makes things easier, no initially but long term, a LOT easier.

Cheers,


Ian
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Ian Price

#8
Matchy and BigSofty - Thankyou for very much your help. That's exactly what I needed.

Actually bigsofty, after changing the directions a few times, the sphere appears to rotate on it's Z axis. Hmmmm... :(

I've changed my code now, and it's getting nearer to what i want - LEFT and RIGHT are always correct, it's just UP/DOWN now that switch positions after a LEFT/RIGHT rotation. I'll keep trying though.

I think the X_SETTEXTUREOFFSET might well be what I need, but in the real code, I need to rotate the object too.

:/

[EDIT] Getting there!
I came. I saw. I played.

bigsofty

Its working fine Ian, its just rather confusing to view what's happening here. When you rotate an object you are rotating its X and Y axis. The little man's head is a good analogy, see the last post. By press up, left, up... he's looking up 90, turning 90 degrees, to the left, looking up again, flips his head 180 (up,up = 180). So he's upside down.

Imagine you were in a space ship taking commands for rotating your craft, up 90, left 90, up 90... you would be facing a upside to the viewers right.

It all object relative. You need to choose a spot on the sphere to see this happening.

Hmmm, cant think of a way to explain it better. :P
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Ian Price

It's OK, now - I re-read your post and it makes sense.

When I re-wrote it though the X axis was always correct, and Y was correct unless I changed the X (rotating it 180) basically.

I've got it working now though (I think). I'm just not hot on 3D.
I came. I saw. I played.

Ian Price

#11
It's OK if you understand those terms and 3D in the first place...  ;) :P

I've actually got it working now (I think - I'll know once it's in the proper game environment).

Cheers. :)


[EDIT] Added .EXE

[attachment deleted by admin]
I came. I saw. I played.

bigsofty

#12
P.S. I heartily  recommend Gernots Entity lib Ian, once you have squashed the basics here. Its a very powerful, easy to use and flexible 3D entity system. Makes rotations (with parent/child entities) a breeze.  It felt very logical to me and therefore easier to visualise the expected results. ;)

Cheers,


Ian
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Ian Price

Cheers, I'll have a look at that at some point, but I won't be needing it for quite some time methinks.

I've got my "ball" moving around properly in a simple, but fully 3D environment now - which I created with my own map editor. It's been quite easy, but I'm not really enjoying developing in 3D just yet.
I came. I saw. I played.