Omnimaga

Calculator Community => Other Calc-Related Projects and Ideas => TI Z80 => Topic started by: TheMachine02 on November 11, 2013, 07:38:34 am

Title: [Axe] - GLib TUTO
Post by: TheMachine02 on November 11, 2013, 07:38:34 am
This is my first tuto ever, so please tell me is something is unclear, or ununderstandable.
New tuto using the new GCORE and final version !

I puting this here, to don't make confusion with other.


First of all, please download the file attached to this post, (not in the GLib main thread, 'cause I didn't update it) (GCORE).
Last version is 2.0 omega
Place it preferably in archive : warning ! this file is pretty huge (6400 bytes !!).


I THE BASIS

Let's create a rotating cube !

First of all, include the GCORE prog inside of your axe source :

Code: [Select]
prgmGCORE

Once you did this you have access to all the GLib functions.


We need to define the 3D coordinates of each point of the cube, so we can rotate and display them afterwards.
Those points are just a bunch of data, so no real explanations are needed here :
Code: [Select]
Data(40r,-40r,40r)->GDB1
Data(40r,40r,40r
Data(-40r,-40r,40r
Data(-40r,40r,40r
Data(40r,-40r,-40r
Data(40r,40r,-40r
Data(-40r,-40r,-40r
Data(-40r,40r,-40r

Just remember that a 3D point is always defined as X,Z,Y using the standard 3D axis (X goes from left to right, Y from down to up and Z from near to far). Each coordinate takes 2 bytes, so don't forget the r.

By default GLib has no camera defined. So we must specify what type of camera we want to use.
In this example, I want to be able to rotate my cube : this is a GMODELVIEW camera (I don't want the camera to move, only the model to rotate). If we actually wanted to have a worldview (fps mode) camera, we would use the °GWORLDVIEW constant.

The function to define a camera is :

Code: [Select]
GNewCam(pointer to camera)
.Destroys r1

**But but but .... I don't know how to create my camera, and I need a pointer to it !
STOP don't worry, GLib provides two pointers to some really basic cameras ! These are the °GMODELVIEW and °GWORLDVIEW cameras.

So I just give one of those pointers to the function and my new camera is created :

Code: [Select]
GNewCam(°GMODELVIEW)
Glib also need a special structure, allowing easy vertex processing/clipping. It's called a VBO : vertex buffer object. Basically, it's just a ram area.
You need at the begining of your program to generate such structure :

This is the command used :
Code: [Select]
GGenVBO(size,data_to_match)
.destroy r1,r2
your size is the number of vertices you want to have.
data_to_match is the raw (not processed) vertices coordinates (here it's GDB1)
It also set the current VBO to the one created , so it will be used by all other command.

The function return a special value, that you have to store somewhere : it's the VBO id.
We now have this :

Code: [Select]
GGenVBO(8,GDB1)->G
.I used G, but you can used any way to save this value


Now we can start the main loop, with 3D calculations :

Code: [Select]
While 1
GUpdateVBO(G,0,7)

this piece of code "update" (transform the vertices) for the specified VBO. You can see that we are passing the id we have previously store.
0 and 7 are the start and the end of vertices we should transform. Here it transform from the vertx 0,...., to the vertx 7 (the last one)

And now we want display our points.
GLib provide the
Code: [Select]
GVBOPoint(id_vertex)
.destroy r1
function to retrieve a point from VBO. It's store the x-coord and y-coord on screen to GScreenX and GSreenY var (alias OP1 and OP1+2)
It also return in hl a clipping information : 0 if the point is visible, anything else (=/= from 0)

We can now write this :
Code: [Select]
For(M,0,7)
GVBOPoint(M)
!If
Rect(GScreenX,GScreenY,2,2
End
End

the code loop from the first vertice, to the last one, retrieve on screen coordinate and then disp it if it is visible.


We need now to handle the arrow keys, so we can rotate our cube. GLib provides an in-built function, which handles everything (life is beautiful isn't it  :P)

It's the GGetkey function.
The call is:
Code: [Select]
GGetkey()

End of the code :

Code: [Select]
GGetkey()

DispgraphClrdraw   // we want to have something on screen !
EndIf getkey(15) // stop the While loop if [clear] is pressed


Now time to compile it ... aaaaaaaaaand ...

(http://i.imgur.com/wcfvbzD.gif)

It works ! :D

II Let's put some line


Well, let's take the previous code we used. He only display dot point, that not super funny. So let's put some line in there !!
In fact, there is almost nothing more to add to your code.
I want to display line, and possibly clipped lines between them. We don't want to draw point, so the previous for() loop is useless.

GLib provide one function for this :
Code: [Select]
GClipLine(ID_vertex1,ID_vertex2)
.destroy r1 to r6
This is assuming that a VBO has been set.

We need however to know what vertices will be linked with. So let's create a list of ID's. Just to remember though :

Code: [Select]
Data(40r,-40r,40r)→GDB1    .vertex ID 0
Data(40r,40r,40r           .vertex ID 1
Data(-40r,-40r,40r         .vertex ID 2
Data(-40r,40r,40r           ...
Data(40r,-40r,-40r
Data(40r,40r,-40r
Data(-40r,-40r,-40r
Data(-40r,40r,-40r

The link between vertices will be handle by an for loop and a constant list (containing the correct vertex ID to link)

so we now have :
Code: [Select]
Data(0,1,2,3,4,5,6,7)->°LinkList
Data(0,2,2,4,4,6,6,0
Data(1,3,3,5,5,7,7,1

and :
Code: [Select]
For(M,0,11)    .there is 12 line to draw in a cube
GClipLine({M*2+°LinkList},{M*2+1+°LinkList}
End

combining all of this , aaaaaaaaand  (yes I like big and) :

(http://i.imgur.com/5ADtj5H.gif)

well I fail in the link data list --'
exercice : find the right data list :p

the whole code, as ever :

Spoiler For Spoiler:
Code: [Select]
.TEST
prgmGCORE

Data(40r,-40r,40r)→GDB1
Data(40r,40r,40r
Data(-40r,-40r,40r
Data(-40r,40r,40r
Data(40r,-40r,-40r
Data(40r,40r,-40r
Data(-40r,-40r,-40r
Data(-40r,40r,-40r

Data(0,1,2,3,4,5,6,7)->°LinkList
Data(0,2,2,4,4,6,6,0
Data(1,3,3,5,5,7,7,1


GNewCam(°GMODELVIEW)
GGenVBO(8,GDB1)->G

While 1

GUpdateVBO(G,0,7)

For(M,0,11)    .there is 12 line to draw in a cube
GClipLine({M*2+°LinkList},{M*2+1+°LinkList}
End


GGetkey()

DispgraphClrdraw
EndIf getkey(15)


correction of the exercice :
Spoiler For Spoiler:
Code: [Select]
Data(0,1,2,3,4,5,6,7)->°LinkList
Data(0,2,2,6,6,4,4,0
Data(1,3,3,7,7,5,5,1


III Shaders (part 1)

you may wonder what is a shader, and what you can do with it. In fact, the shader is a way to override the static pipeline of the 3D calculations. You are able then to do a lot of thing with it. However, some vars, (r3 to r6) musn't be used inside shader functions, due to GLib using these.

Well, anyway, let get started !
The standard function to set a shader is :

Code: [Select]
GVertexShader(adress_of_function,sub_adress_projection)
.destroy r1,r2
you can of course get the adresse with the L operator.
sub_adresse_projection is kindy tricky. It is the adresse in your shader, where th projection calculation starts.

Once you've put this code, anywhere in your  program, GLib's functions will get override.

So let's see what you have to put inside this function.

Code: [Select]
Lbl Shader
GRestoreHL

Return

because some function need a correct hl you mostly want to restore it. As GLib do a goto before, hl get ecrased. But we have a variable to restore it  ;D

a very basic shader (do nothing more than the GLib's GVertex command) would be then this:

Code: [Select]
Lbl Shader
GRestoreHL
GRotate()
Lbl SubShader   .the famous sub_adress
Goto GProject


it's first call the fuction who convert the r1,r2,r3   (and need r3 in hl) to the rotated coordinate in 3D space into OP1+6
Code: [Select]
GRotate(x,z,y)
.destroy r1-r3
.write to OP
You will then have the vertex rotated coordinate to these variable :

Code: [Select]
GVertexX
GVertexY
GVertexZ

Then it call the projection function to retrieve the x,y coordinate on screen

Code: [Select]
GProject()
.need the 3D coordinate Inside OP1+6 (°GVertex+6)

...and you can retrieve the 2D coordinate to these vars : (note that this function keep the 3D coordinates safe)

Code: [Select]
GScreenX
GScreenY

Based on this you can either :
-modify the vertex position before any rotation or after
-build your own rotation routine and projection (for example to have more precision)
-and everything you want...

Once you've done with the shader, you can disable it by doing :
Code: [Select]
GVertexShader(°GLIBFUNC)
yep it's the same function  :P  pretty easy isn't it ?

let's create a custom shader then  ;D
The goal is to make the camera moving up and down like in old fps. When the player is not moving, there should be no mouvement.
Let create a vars T who hold the current active/not active state. Each frame, compare the X,Y coordinate of the player with previous stored one. (A,B) - if it different, increase the Z var, use to hold an angle : the cosinus will give us the mouvemnt.

We now have this as shader :
Code: [Select]
Lbl TEST
GRestoreHL
GRotate()
Lbl TESTSUB
GProject()
!If T
signed{Z^256+°GCos}//32+GScreenY+2->GScreenY
End
Return

for each vertex, the point will be move on screen.

And then in the main loop, add this:

Code: [Select]
0->T
!f A-GCPosX   .GCPosX is the X coordinate of the camera
!f B-GCPosY
+1->T   .hl abuse...
End
End

GCPosX->A
GCPosY->B
If T
96->Z
Else
Z+8->Z   .increase the angle, so we can have the mouvement
End


and with variables initialisation :

Code: [Select]
0->A->B->T

So the whole code is :
(note that I change vertices to be more a world thing)
Spoiler For Spoiler:
Code: [Select]
.TEST
prgmGCORE

Data(-64r,0r,64r)→GDB1
Data(64r,20r,64r
Data(-64r,0r,64r
Data(-64r,20r,64r
Data(64r,0r,-64r
Data(64r,20r,-64r
Data(-64r,0r,-64r
Data(-64r,20r,-64r

Data(0,1,2,3,4,5,6,7)->°LinkList
Data(0,2,2,4,4,6,6,0
Data(1,3,3,5,5,7,7,1


GNewCam(°GWORLDVIEW)
GGenVBO(8,GDB1)->G

0->A->B->T
GVertexShader(LTEST,LTESTSUB)  .actually the small liste operator.

While 1

GUpdateVBO(G,0,7)

For(M,0,11)    .there is 12 line to draw in a cube
GClipLine({M*2+°LinkList},{M*2+1+°LinkList}
End

0->T
!f A-GCPosX   .GCPosX is the X coordinate of the camera
!f B-GCPosY
+1->T   .hl abuse...
End
End

GCPosX->A
GCPosY->B
If T
96->Z
Else
Z+8->Z   .increase the angle, so we can have the mouvement
End

GGetkey()

DispgraphClrdraw
EndIf getkey(15)
Return

Lbl TEST
GRestoreHL
GRotate()
Lbl TESTSUB
GProject()
!If T
signed{Z^256+°GCos}//32+GScreenY+2->GScreenY
End
Return

well, screen have different vertices but run the same shader :

(http://i.imgur.com/NGe0spR.gif)

One thing to remember :
DO NOT USE r4 to r6 !!. r1-r3 are fine though (but only after rotating)


IV And then come polygons.... [WARNING OUTDATED ]


the polygon system is in a separate library. So to use it, download the GPOLYGON file, and then put :

Code: [Select]
prgmGPOLYGON

a little warning : GPOLYGON is in alpha, bug may still there ! (and so ram clear too =\)

at the begin of your program, after the inclusion of the GCORE file. You can then acess all the new functions !

There is 3 extremely important function :
Code: [Select]
GDrawArray(adr_array,nb_of_poly)
.destroy r1 to r6
GPrimitive(start_adr)
.destroy r1 to r6
GSetColor(flag)
.destroy r1


I'll first explain GSetColor and GDrawArray, later GPrimitive

GSetColor is I guess pretty obvious. It is used to set the current drawing color.
Two flag are possible :
°GBLACK or °GWHITE (yes, it's constants)

every polygon drawn will have the color you set. Black is the default color.

GDrawArray can draw polygons according to a big bunch of datas. Data have a particular structure :

Code: [Select]
Data(Type_polygon,Color
Data(idVertex1,idVertex2,...
.all of this is one byte value

This function handle 3 type of polygon, with a special one :
-triangles       type is °GTRI
-quadrilater    type is °GQUAD
-sphere          type is °GSPHERE

the number of vertices you want to put is obviously the number of vertices in the polygon.

Why I say sphere is a special thing ? Cause data structure is different :

Code: [Select]
Data(type,color)
Data(centerVertexId,radius

where the centerVertexId is the id of the vertex representing the center of the sphere.

and then the GPrimitive function. I guess this is the most difficult.

the GPrimitive function take in input the pointer to a list of vertices' id, an you must set a particular variable before the call ; the GPolygon var.
Simply put the type ( the constant ) in it. The call will the look like this :

Code: [Select]
GSetColor(°GBLACK)
°GTRI->Gpolygon
GPrimitive(Data(0,1,2))

it wil draw, in black, a triangle between the first three vertex.

One last thing before the test code though, you remember the GVAdr and GVStr variables for the line clipping ? Well polygon work the same. Every function need correct value in these var.
Meaning that you have to rotate your vertex, store them, before call the Polygon function.  :P  If a polygon you draw goes crazy, look if you don't forget this part.

And now, a little test program:


Code: [Select]
.TEST
prgmGCORE
prgmGPOLYGON

Data(40r,-40r,40r)→GDB1
Data(40r,40r,40r
Data(-40r,-40r,40r
Data(-40r,40r,40r
Data(40r,-40r,-40r
Data(40r,40r,-40r
Data(-40r,-40r,-40r
Data(-40r,40r,-40r

Data(0,1,2,3,4,5,6,7)->°LinkList
Data(0,2,2,4,4,6,6,0
Data(1,3,3,5,5,7,7,1

Buff(8*6)→GDB2


GNewCam(°GMODELVIEW)
GDB1→GVAdr
GDB2→GVStr

While 1

GDB1→r5
GDB2→r6

For(8)
GVertex({r5}r,{r5+2}r,{r5+4}r
copy(°GVertex,r6,6
r6+6→r6
r5+6→r5
End

For(M,0,11)    .there is 12 line to draw in a cube
GClipLine({M*2+°LinkList},{M*2+1+°LinkList}
End

°GQUAD->GPolygon
GPrimitive(Data(0,1,3,2))
.warning ! vertex must be clockwise or anticlockwise!

GGetkey(°GMODEL)

DispgraphClrdraw
EndIf getkey(15)


not much change ,heh ?
and the screen =)
(http://i.imgur.com/IC08umU.gif)

still pretty strong, running at 20fps with a fully clipped model.

V VBO, extra functions, and pipeline informations...

We have already talked about VBO ... but how they work precisely ? follow the guide !

VBO are just a free place in memory, with an particular structure, and an id.
What is a VBO Id ? In fact, it is no more than the adress of the start of it.
Base on that, we can perfectly create our own VBO, without passing by the GGenVBO() command.You can perfectly, is L3 has been perfectly set up use this :
Code: [Select]
GSetCurVBO(L3)
.destroy r1

Bascially this command will change the current active VBO (read : used for rendering) to the one you specify.
So, what is this particular structure ? It is the following :

Code: [Select]
.1 bytes                              -- reserved field for GLib's, used for delete VBO (you don't really need this)
.2 bytes                              --number of vertices the VBO should handle at max
.2 bytes                              --raw vertices adress
.5*number of vertices bytes --the vertex on screen position, with their respective cliping code
.6*number of vertices bytes --the rotated vertices coordinates.

the screen coordiante is separate as follow :

Code: [Select]
.2 bytes X coordinate
.2 bytes Y coordinate
.1 byte clipping code

the cliping code can be computed, if the vertex position to classify is in the GVertexX to GVertexZ vars with :
Code: [Select]
GInFrustrum()/256
.destroy nothing
and return vertex status in hl :
-0 if the point is visible
-anything else if not


Now more about the GLib's pipeline. In fact, when you want to draw a line, or any polygon, the classical pipeline will be :
(http://i.imgur.com/RN8TzuL.png)

-green : vertex operation
-red : shader
-blue : geometric operation
-white : outside GLib data operation.

Indeed, this is a simplified one - especially into the graphics commands. The last stage can be decomposed in many other one, but the GCORE lib doesn't really touch these. It's more the goal of the GPOLY lib (wich is for the moment outdated).


Other tutorials are coming, I will then organize this post with them.
Title: Re: [Axe] - GLib TUTO
Post by: Matrefeytontias on November 11, 2013, 09:27:03 am
At last ! A tutorial ! :D

I'll sure be fiddling with that after I'd cleaned up my calc (3k of archive is not the optimal free space to work with) :P
Title: Re: [Axe] - GLib TUTO
Post by: Sorunome on November 11, 2013, 09:32:52 am
Ui, a tutorial for this, that helps understand how it works a lot :)/me hops people will start using it now
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on November 11, 2013, 09:36:34 am
Ui, a tutorial for this, that helps understand how it works a lot :)/me hops people will start using it now

I hope too  :P  that why I make the lib a lot simpler (and a tuto)
The thing I found funny, is as I make the lib simpler, I make it faster  ;D
Title: Re: [Axe] - GLib TUTO
Post by: Streetwalrus on November 11, 2013, 12:22:08 pm
Sounds interesting. Definitely gonna try it out. ;)
Title: Re: [Axe] - GLib TUTO
Post by: ben_g on November 11, 2013, 04:09:06 pm
This is a good and easy to follow tutorial, and I was amazed at the speed of this thing: 55fps on 6MHz and 75fps on 15MHz!
/me is deffinately going to use this in some programs.

I did notice a small mistake in the full code, though: you did
rect(,{°GVertex+2}r,2,2
instead of
Rect({°GVertex}r,{°GVertex+2}r,2,2
It is correct in the tutorial itself, but I thougth it would be best to report this.
Title: Re: [Axe] - GLib TUTO
Post by: nikitouzz on November 11, 2013, 04:14:39 pm
If i can critique one thing :p

I like this tutorial but i thinks that the name of your routine is a lot of big example : GNewCam(pointer to camera) can be Camera(pointer to camera) this is more clear when we read the code :)
Title: Re: [Axe] - GLib TUTO
Post by: Streetwalrus on November 11, 2013, 04:30:21 pm
This is a good and easy to follow tutorial, and I was amazed at the speed of this thing: 55fps on 6MHz and 75fps on 15MHz!
/me is deffinately going to use this in some programs.

I did notice a small mistake in the full code, though: you did
rect(,{°GVertex+2}r,2,2
instead of
Rect({°GVertex}r,{°GVertex+2}r,2,2
It is correct in the tutorial itself, but I thougth it would be best to report this.
If you read closer, this is an HL abuse, no mistake here. ;) Just that it's a bit less clear for a tutorial.
Title: Re: [Axe] - GLib TUTO
Post by: ben_g on November 11, 2013, 04:37:02 pm
Oh, I just assumed that it was wrong because it was different in the tuturial as in the full code. I don't really know many of the axe optimisation tricks.
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on November 12, 2013, 02:44:51 am
This is a good and easy to follow tutorial, and I was amazed at the speed of this thing: 55fps on 6MHz and 75fps on 15MHz!
/me is deffinately going to use this in some programs.

I did notice a small mistake in the full code, though: you did
rect(,{°GVertex+2}r,2,2
instead of
Rect({°GVertex}r,{°GVertex+2}r,2,2
It is correct in the tutorial itself, but I thougth it would be best to report this.

Yeah it's just an hl optimization. I started to put it, and then I think " we are in a tuto, so I preferably not put it" aaand I forget correct the final code  ;D

If i can critique one thing :p
no you can't
/me run

I like this tutorial but i thinks that the name of your routine is a lot of big example : GNewCam(pointer to camera) can be Camera(pointer to camera) this is more clear when we read the code :)

mmmhh maybe, but the problem is there is not only one command GNewCam, there is also  GDelCam, GSwitchCam, and GUpdateCam, so I prefer to have some global name aspect.

This is a good and easy to follow tutorial, and I was amazed at the speed of this thing: 55fps on 6MHz and 75fps on 15MHz!

and there is hidden way to go even faster !  I will said some tips in other tuto  ;)
Anyway happy you like it  :D
Title: Re: [Axe] - GLib TUTO
Post by: DJ Omnimaga on November 12, 2013, 03:13:35 am
It would definitively be nice if you could expand the tutorial further so that it also teaches how to make programs where the dots are connected with lines or maybe even textures. :)

Also maybe uploading a copy of the tutorial at http://www.omnimaga.org/index.php?action=articles;cat=12 when it's completed. :)
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on November 12, 2013, 06:39:05 am
It would definitively be nice if you could expand the tutorial further so that it also teaches how to make programs where the dots are connected with lines or maybe even textures. :)

The dot connected thing is the next tuto comming  :P , I wil complete it soon, so maybe this evening (if I am fast) or tomorrow.
I will talk after of the use of vertex shader

As a side note I spot a very very bad bug in GCORE  ;D  , causing clipping not work proprelly. I fixed it easely, but I  need to release it (and remove the old download) (so this evenning, I release it, with the fixed version of shader)

EDIT : attach  the correct version to the first post -- I made some cleanning, so file is not so huge now
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on November 14, 2013, 01:02:51 pm
Tutorial as been updated  ;D
Title: Re: [Axe] - GLib TUTO
Post by: Streetwalrus on November 14, 2013, 03:55:22 pm
Wow super cool stuff as always ! :D
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on December 03, 2013, 01:29:31 pm
new tuto on Shader !
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on December 08, 2013, 12:44:13 pm
Well well well I may have release the GPOLYGON library  ;)
Title: Re: [Axe] - GLib TUTO
Post by: ben_g on December 27, 2013, 12:57:17 pm
I have created a simple example program to show how you can use GLib in a game.
It handles basic wireframe rendering, as you can learn from the tutorials, but it also shows you how to make a dynamic level, a way to use very large levels without getting accuracy problems, and a way to move the camera in an other way than by GLib's GGetKey() function.

This is a screenshot of how it looks:
(http://img.ourl.ca/3D%20tunnel%20test-1.gif)

You can find the partially commented 8xp file in the attachement. The full source code in ASCII format with more comments can be found in the spoiler below.
Spoiler For "Source code":
.TUNNEL3D

.INCLUDE GLIB
prgmGCORE

.Add a world view camera, and set the coordinates to (0,0,0)
GNewCam(^^oGWORLDVIEW)
0->GCPosX->GCPosY->GCPosZ

.Set up the vertex buffers. VBuff is for the world space vertices, VBuff2 is for the screen space (transformed) vertices
L2->^^oVBuff->GVAdr
L3->^^oVBuff2->GVStr

.The sprites for the player and their masks
[0000007E997E0000]->GDB1
[00007EFFFFFF7E00]
[00183C7E997E0000]
[183C7EFFFFFF7E00]
[00007EFFFFFF7E3C]
[0000007EFF7E3C18]
[00003E2E1E0A0600]
[003E7F7F3F1F0F06]
[00007C7478506000]
[007CFEFEFCF8F060]

.Generate a straight tunnel in which the player will start
^^oVBuff->A
5->B
For(15)
~20->{A}^^r
B->{A+2}^^r
~20->{A+4}^^r

20->{A+6}^^r
B->{A+8}^^r
~20->{A+10}^^r

20->{A+12}^^r
B->{A+14}^^r
20->{A+16}^^r

~20->{A+18}^^r
B->{A+20}^^r
20->{A+22}^^r

A+24->A
B+10->B
End

.Set up the variables
.Used for the level generator: F and G represent the X and Y coordinates of the center of the last tunnel frame
.J and K represent the angle of the tunnel segment that needs to be generated
.H and I are counters used to determine the length of the tunnel piece being generated (because of this, the tunnel is a series of bents instead of randomly displaced squares
0->F->J
0->G->K
0->H
0->I
.S is the score (number of frames since the start of the game)
0->S

.SETUP OTHER STUFF (makes the text being drawn on the buffer, and inverted)
Fix 3
Fix 5

.MAIN GAME LOOP
Repeat getKey(15)

.MOVE THE CHARACTER
.The +3 is the speed of the player in the Y-direction.
GCPosY+3->GCPosY
    .If the character's Y-position is greater than 10, then the world has to be moved backwards by 10 units (this way, the player never gets away too far from the orgin, so that there won't be problems with overflows)
If GCPosY>10
GCPosY-10->GCPosY
.SHIFT WORLD
Copy(^^oVBuff+24,^^oVBuff,336)
^^oVBuff+2->A
For(60)
{A}^^r-10->{A}^^r
A+6->A
End

.Generate a new tunnel piece. This is done by adding random offsets to the center of the squares, but it adds the same offset multiple times to make it look more like a neat tunnel instead of a random mess.

If H=0
rand^17-8->J
rand^(20-abs(J))+1->H
End
If I=0
rand^17-8->K
rand^(20-abs(K))+1->I
End

H--
I--

S/256->B

F+J->F
G+K->G

        .Add the vertices for the new tunnel piece

^^oVBuff+336->A

F-20+B->{A}^^r
145->{A+2}^^r
G-20+B->{A+4}^^r

F+20-B->{A+6}^^r
145->{A+8}^^r
G-20+B->{A+10}^^r

F+20-B->{A+12}^^r
145->{A+14}^^r
G+20-B->{A+16}^^r

F-20+B->{A+18}^^r
145->{A+20}^^r
G+20-B->{A+22}^^r

End

.CONTROLS: move the player based on what kays are pressed. The *2 determines the speed at which the player can move in the XZ plane
getKey(3)-getKey(2)*2+GCPosX->GCPosX
getKey(4)-getKey(1)*2+GCPosZ->GCPosZ

.CHECK IF PLAYER DIED

GCPosX->A
GCPosZ->B
^^oVBuff+48->C

If {C}^^r+2>>A or ({C+4}^^r+2>>B) or ({C+12}^^r-2<<A) or ({C+16}^^r-2<<B)
        .If the player is within 2 units from an edge of the third frame, then the player died and the program is terminated (we use the third frame because the camera appears behind the player)
Goto END
End

.TRANSFORM THE VERTICES (This basically does the same as the tutorial)
^^oVBuff->A
^^oVBuff2->B
For(60)
GVertex({A}^^r,{A+4}^^r,{A+2}^^r)
Copy(^^oGVertex,B,6)
A+6->A
B+6->B
End

.DRAW THE TUNNEL
ClrDraw
    .Because the tunnel consists of simple squares, the vertices can be connected by a very simple algorithm, so that we don't need to read them from a link list
0->E
For(15)
For(3)
GClipLine(E,E+1)
E++
End
GClipLine(E,E-3)
E++
End

.Draw the score
Text(0,0,S>Dec)
S++

.Draw the correct player sprite, based on the keys being pressed
If getKey(3)
Pt-Mask(44,28,GDB1+48)^^r
ElseIf getKey(2)
Pt-Mask(44,28,GDB1+64)^^r
ElseIf getKey(1)
Pt-Mask(44,28,GDB1+32)^^r
ElseIf getKey(4)
Pt-Mask(44,28,GDB1+16)^^r
Else
Pt-Mask(44,28,GDB1)^^r
End

DispGraph
End

Lbl END

.Restore the text flags
Fix 2
Fix 4

Ps: do you want a challenge? Put a Full at the start, and/or increase the Y and XZ speeds by the same factor (example of a doubled speed + 15MHZ (=5x normal speed)). (http://img.ourl.ca/3D%20tunnel%20test%202.gif)
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on December 28, 2013, 05:10:45 am
Wow I love this. I think it will have his place in the GLib's example folder  :P


EDIT ; by the way, you don't need to set cam coordinate to 0', cause GNewCam already do that normally.

EDIT2 : after verif, only GCPosZ should be set to 0 . In fact,  °GWORLDVIEW implement an eye offset, wich is 10 by default.
I you want to have an optimized thing, you can set the constant °GEyeOffset to 0 (before GCORE as usual) , and there will be no need to set camera's coordinate to 0.
Title: Re: [Axe] - GLib TUTO
Post by: pimathbrainiac on December 28, 2013, 11:56:12 am
Great job ben_g

/me is expecting a Starfox 64-like sometime soon.
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on December 28, 2013, 12:55:26 pm
Maybe a very simple one is possible  :P . Anyway, I am really impressed that it run so fast (60 vertices are rotated and projected each frame) .... and it's me who say that  :P

/me hides
Title: Re: [Axe] - GLib TUTO
Post by: Sorunome on January 04, 2014, 05:31:04 am
That tunnel is just epic o.o
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on January 14, 2014, 01:44:17 pm
New tuto using the new GCORE and final version !

I puting this here, to don't make confusion with other.


First of all, please download the file attached to this post, (not in the GLib main thread, 'cause I didn't update it) (GCORE).
Last version is 2.0 omega
Place it preferably in archive : warning ! this file is pretty huge (6400 bytes !!).


I THE BASIS

Let's create a rotating cube !

First of all, include the GCORE prog inside of your axe source :

Code: [Select]
prgmGCORE

Once you did this you have access to all the GLib functions.


We need to define the 3D coordinates of each point of the cube, so we can rotate and display them afterwards.
Those points are just a bunch of data, so no real explanations are needed here :
Code: [Select]
Data(40r,-40r,40r)->GDB1
Data(40r,40r,40r
Data(-40r,-40r,40r
Data(-40r,40r,40r
Data(40r,-40r,-40r
Data(40r,40r,-40r
Data(-40r,-40r,-40r
Data(-40r,40r,-40r

Just remember that a 3D point is always defined as X,Z,Y using the standard 3D axis (X goes from left to right, Y from down to up and Z from near to far). Each coordinate takes 2 bytes, so don't forget the r.

By default GLib has no camera defined. So we must specify what type of camera we want to use.
In this example, I want to be able to rotate my cube : this is a GMODELVIEW camera (I don't want the camera to move, only the model to rotate).

The function to define a camera is :

Code: [Select]
GNewCam(pointer to camera)
.Destroys r1

**But but but .... I don't know how to create my camera, and I need a pointer to it !
STOP don't worry, GLib provides two pointers to some really basic cameras ! These are the °GMODELVIEW and °GWORLDVIEW cameras.

So I just give one of those pointers to the function and my new camera is created :

Code: [Select]
GNewCam(°GMODELVIEW)
Glib also need a special structure, allowing easy vertex processing/clipping. It's called a VBO : vertex buffer object. Basically, it's just a ram area.
You need at the begining of your program to generate such structure :

This is the command used :
Code: [Select]
GGenVBO(size,data_to_match)
.destroy r1,r2
your size is the number of vertices you want to have.
data_to_match is the raw (not processed) vertices coordinates (here it's GDB1)
It also set the current VBO to the one created , so it will be used by all other command.

The function return a special value, that you have to store somewhere : it's the VBO id.
We now have this :

Code: [Select]
GGenVBO(8,GDB1)->G
.I used G, but you can used any way to save this value


Now we can start the main loop, with 3D calculations :

Code: [Select]
While 1
GUpdateVBO(G,0,7)

this piece of code "update" (transform the vertices) for the specified VBO. You can see that we are passing the id we have previously store.
0 and 7 are the start and the end of vertices we should transform. Here it transform from the vertx 0,...., to the vertx 7 (the last one)

And now we want display our points.
GLib provide the
Code: [Select]
GVBOPoint(id_vertex)
.destroy r1
function to retrieve a point from VBO. It's store the x-coord and y-coord on screen to GScreenX and GSreenY var (alias OP1 and OP1+2)
It also return in hl a clipping information : 0 if the point is visible, anything else (=/= from 0)

We can now write this :
Code: [Select]
For(M,0,7)
GVBOPoint(M)
!If
Rect(GScreenX,GScreenY,2,2
End
End

the code loop from the first vertice, to the last one, retrieve on screen coordinate and then disp it if it is visible.


We need now to handle the arrow keys, so we can rotate our cube. GLib provides an in-built function, which handles everything (life is beautiful isn't it  :P)

It's the GGetkey function.
The call is:
Code: [Select]
GGetkey()

End of the code :

Code: [Select]
GGetkey()

DispgraphClrdraw   // we want to have something on screen !
EndIf getkey(15) // stop the While loop if [clear] is pressed


Now time to compile it ... aaaaaaaaaand ...

(http://i.imgur.com/wcfvbzD.gif)

It works ! :D
Title: Re: [Axe] - GLib TUTO
Post by: TheCoder1998 on January 14, 2014, 01:45:09 pm
wow, this looks awesome :D
great job on the tutorial!

EDIT: Since when is 6400 bytes pretty huge? :P (i've got an SE)
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on January 14, 2014, 01:45:51 pm
thanks  :D
Title: Re: [Axe] - GLib TUTO
Post by: Matrefeytontias on January 14, 2014, 02:17:36 pm
Nice explanation :) will you include a specific chapter about VBOs too ?

IMO you should just erase the whole previous chapter 1 and replace it by this one.
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on January 14, 2014, 02:19:17 pm
yep, I will explain VBO - especially for the structure. So you can still generate Vertex on fly  :P


EDIT : tuto have been placed on the first post, with warning for those unupdated.
Title: Re: [Axe] - GLib TUTO
Post by: ben_g on January 14, 2014, 05:01:28 pm
I've downloaded the GCORE version of the tutorial post (edit: it says "Version 2.0 omega" in the program editor), and when I try to use it, it thrown an undefined error at GGenBuffer and GUpdateBuffer.
I've checked them for typing mistakes, but they looked correct.
What am I doing wrong?

EDIT2: I've looked at the source code, and it looks like it should be GGenVBO and GUpdateVBO instead of GGenBuffer and GUpdateBuffer. It works with those.
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on January 15, 2014, 02:00:40 am
O_o I guess I've change the syntax, and I forget that I've chnage it. Thanks for the report  ;D . The tuto have been updated.
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on February 05, 2014, 12:29:28 pm
.....soooooo I have finally updated the tuto talking about lines and shader  ;D
Title: Re: [Axe] - GLib TUTO
Post by: Matrefeytontias on February 05, 2014, 02:49:45 pm
Cool o/

Can you give an example of what the vertex shader could be used for ? I can't really think of any use for it, but it's only because I lack imagination.
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on February 05, 2014, 03:11:03 pm
Adding that right now  :P*


EDIT : done  :D
Title: Re: [Axe] - GLib TUTO
Post by: Matrefeytontias on February 05, 2014, 04:57:46 pm
Oooh that's a nice use :D of course I didn't think of that :P
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on February 08, 2014, 05:41:34 pm
added some info about vbo, but Idk what I can do on this subject/ supplementary info to add.  :P
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on February 12, 2014, 07:56:06 am
* added some pipeline info
* fix some typos (but many is still there I guess  :P )
Title: Re: [Axe] - GLib TUTO
Post by: Matrefeytontias on February 12, 2014, 01:07:12 pm
Where are those "extra functions' you talk about ? :P

EDIT : also, it would be worth noting that r4 to r6 can't be used in a vertex shader due to GUpdateVBO using them in the For loop. Took me some time to understand why my program wasn't working.
Title: Re: [Axe] - GLib TUTO
Post by: TheMachine02 on February 13, 2014, 06:31:53 am
Where are those "extra functions' you talk about ? :P

Function used to manage camera / camera sructure :p

EDIT : also, it would be worth noting that r4 to r6 can't be used in a vertex shader due to GUpdateVBO using them in the For loop. Took me some time to understand why my program wasn't working.

Indeed. I have added that