Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit/AppGameKit Studio Showcase / The road to nobody knows where (endless track)

Author
Message
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 2nd Dec 2015 14:04 Edited at: 6th Dec 2015 21:22
I have been persuaded by spectrePaul to start a thread on my venture into the unknown - quite literally. I hope others will learn from my trials as I learn new skills and put them into something almost useful. I will share code as well as experiences as I tread into the abyss.

The Challenge
I will be making an endless track, probably in the form of a Rollercoaster. The ultimate goal is to make it compatible with Google Card or maybe even Oculus Rift. But that is a long way down the road, so to speak.

The Milestones
There are some things I need to achieve along the way, and more will creep in as I progress.

Making meshes - the track will be dynamically built, there is no pre-determined path. So 3D meshes need to be built on the fly
Making Splines - the secret to a good - random - rollercoaster lies in splines. These enable you to make smoothly meandering curves in 3D space and so will be essential
Bolting bits together - I will need to bolt meshes onto splines in a way that resembles a track, and do it efficiently. This will require unbolting too.
Shader stuff - Making the track look...track-like...will require shaders, normal mapping, bump mapping and other such things I don't yet know about.

Modularisation
Anyone who has read my tutorials will know I like to modularise. I hope to produce code that people can lift out and drop into other projects.

So, here goes something...

All of the official posts are in this thread, but separated by lots of discussion...
Chapter 1.1 - Mesh Mania
Chapter 1.2 - Deconstructing a Plain
Chapter 1.3 - Making a Plain from Nothing
Chapter 1.4 - Helper Functions
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 2nd Dec 2015 14:14 Edited at: 3rd Dec 2015 20:33
Chapter 1.1 - Mesh Mania
Making a track that has no shape before it exists will involve creating the mesh from nothing. We could use pre-built pieces but I have decided against that for 3 reasons:

1. It limits what you can achieve to the pieces available. It would be like trying to make a water slide from lego, which would only lead to injuries and embarrassment.
2. I will spend more time making new pieces for new requirements and the library will grow, become more cumbersome and harder to find what you need.
3. It's not as much fun.

AGK has the ability to manipulate 3D object meshes in memblocks. If you haven't discovered memblocks yet, you really should look into how they work. They allow manipulation of data at a very low level, and they allow you to do it quickly.
The commands we have available for memblock meshes are :




As I have started this part of the project before I started writing about it, I can reveal that I have decided to fast-track the creation of the basic track piece. At this stage I am simply using Planes:

This keeps the basic coding techniques simple
I hope to make the Planes a little more lifelike later on with the use of shaders.
The number of vertices is minimal, making the track much more efficient.

Next post, I will look at the detail of the memblock mesh.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
SpecTre
Developer
16
Years of Service
User Offline
Joined: 24th Feb 2003
Location: UK
Posted: 2nd Dec 2015 17:10
Hey BatVink!!! glad you decided to put this in the showcase section, I am really looking forward to seeing where you go with this. The showcase section is my favourite part of the forums, especially when projects that are really interesting like this one are put on here!

Good luck with it and looking forward to the next instalment
The Amiga and Amos were great!
My website LEAP - Download Paint Pot here!
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 4th Dec 2015 10:26
Chapter 1.2 - Deconstructing a Plain

We can easily look inside the construction of a mesh by making a memblock from it. Using a Plain is the best way to learn, as it is a very simple mesh, but has a few tris (Triangles) to work with.

A Plain has:

2 sides, top and bottom
4 tris to make up the top and bottom quads (2 triangles to make up a quadrilateral shape)
12 vertices - one per corner of each tri

Putting it in a memblock exposes all of this information, including position, the normals (which direction the vertex faces) and the UV coordinates (used to map the texture, colours and other elements).
But it is still a complex beast to iterate through and understand the data. So step 2 is to put the pertinent information into a usable structure. Here's the structure:



Some important constants:



Here is the Array that we will use to store multiple mesh structures:



And here is a function for getting all of that juicy information out. It returns an array element ID so you can find it again later:



It duplicates some standard functionality, but this is a precursor to finding additional data such as bones and other optional attributes.
Next post, we will create some helper functions to get and manipulate some of this data.

In terms of our Plain, this is what we get:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
SoftMotion3D
AGK Developer
14
Years of Service
User Offline
Joined: 24th Aug 2005
Location: Calgary,Alberta
Posted: 5th Dec 2015 15:30 Edited at: 5th Dec 2015 15:52
are you familiar with indexes?

if not i can help you out and explain.

an index set of 3 or 4 is what links the 3d vertex data together to form triangles or quads of an object. my experience is strictly with triangles linking vertex data in sets of 3.
the way an index is linked tells the 3d engine which way the triangle is facing. if i was looking at a 3d cube in my scene then the indexes would need to be linked clockwise. If i was inside the cube and wanted to see the walls of it.... the indexes would need to be linked counter clockwise (if i was drawing the faces from outside of the cube). If you would appear to be able to see the triangle mesh from the way you are facing then it would be clockwise.... may sound confusing but once you begin to play around with meshes you will figure it out.

i have not looked at agks new memblock commands yet but have already coded my own that produces obj files and just loads them back in.
with my experience i will tell you that agk does not like 100's of objects on the screen at once. If you can combine as many objects into a few objects you will have much better performance.

a plain object could have much less data then you describe.

4 vertexes
6 indexes

each vertex data can hold x,y,z normals and u,v data

thats it. 2 triangles creating a plain.

vertex data can be shared from index to index... sharing them is what makes the object a solid face shape. The only time its not shared is when uv data and / or normals data needs to be different then an existing vertex data has in the same 3d space.
www.sheldonscreations.com
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 5th Dec 2015 16:00
Thanks for the info. I have been considering whether to use indexes (indices?), although I have never used them before so any help is gratefully received. I was a little surprised to find that the AppGameKit primitives don't use indexes. It simply takes the vertex data in sets of 3 and makes triangles from them. In something as simple as a Plain you have:

12 vertices
0 indexes

With indexes you would have:

4 vertices
12 indexes

But more importantly you would have an easier way to manipulate the Plain. For each corner, you have to move up to 4 vertices in synchronisation with one another. This would be reduced to just one vertex move in an indexed model. Also the vertex data is far more complex than the index data, so the mesh data would be smaller, not larger. Non-indexed meshes get even more complex when you want to manipulate UV and normal data, not to mention more complicated attributes.

Question: Are there any downsides to using indexes? For example, is it going to screw up my normals in a 2-sided Plain?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
Preben
AGK Studio Developer
15
Years of Service
User Offline
Joined: 30th Jun 2004
Location:
Posted: 5th Dec 2015 16:51
You do not loose any normals when you use faces.

( indexes (indices?) ) and faces , you define the vertex/texture/normal and what 3 points (vertex/texture/normal) that connect the polygon in the face/indices/index setup , so i cant see it work without , perhaps agk defines the faces when/if there is not anything defined ?

but SoftMotion3D is the real master here


best regards Preben Eriksen,
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 5th Dec 2015 18:13
Quote: "You do not loose any normals when you use faces."


It is more about the direction of the normal, I am a novice in this area so my understanding could be way out.
If a normal point upwards (+Y) for the upper faces, then how does it affect the underside faces that are using the same normal, but facing downwards?

Quote: "so i cant see it work without , perhaps agk defines the faces when/if there is not anything defined ?"

It definitely has no indexes, the help files say that it simply uses the vertices 3 at a time to make the faces, when there are no indexes. I remember from my DBPro days that this was the case with 3DS models.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 5th Dec 2015 21:23 Edited at: 5th Dec 2015 21:25
This is what I mean by the normals. In the AppGameKit Plain...



0.094, Vertex 0, 0.0, 0.0, -1.0
0.094, Vertex 1, 0.0, 0.0, -1.0
0.094, Vertex 2, 0.0, 0.0, -1.0
0.094, Vertex 3, 0.0, 0.0, -1.0
0.094, Vertex 4, 0.0, 0.0, -1.0
0.094, Vertex 5, 0.0, 0.0, -1.0
0.094, Vertex 6, 0.0, 0.0, 1.0
0.094, Vertex 7, 0.0, 0.0, 1.0
0.094, Vertex 8, 0.0, 0.0, 1.0
0.094, Vertex 9, 0.0, 0.0, 1.0
0.094, Vertex 10, 0.0, 0.0, 1.0
0.094, Vertex 11, 0.0, 0.0, 1.0


One face points one direction, and the other face points in the other. Will a mesh with 4 vertices look wrong because the underside normals are facing the wrong direction?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
SoftMotion3D
AGK Developer
14
Years of Service
User Offline
Joined: 24th Aug 2005
Location: Calgary,Alberta
Posted: 5th Dec 2015 21:30
Quote: "It is more about the direction of the normal, I am a novice in this area so my understanding could be way out.
If a normal point upwards (+Y) for the upper faces, then how does it affect the underside faces that are using the same normal, but facing downwards?"


are you trying to make a plain thats visible from both bottom and top?

a normal plain object can only be seen from one side and the other will be completely see through. (unless you set the cull option) If the cull option is used i believe that the normals are reversed automatically if your camera is on the other side of the object facing it. so no need to worry about that.

question though... did you say you cannot set index data with agks memblock? if this is the case then that really sucks! the index data is what defines the triangles or quad faces of the 3d object.

a single triangle would look like this:
v,x,y,z
vertex 0,-10,0,10
vertex 1,10,0,10
vertex 2,10,0,-10

now to say its facing up

v,x,y,z
normal 0,0,1,0
normal 1,0,1,0
normal 2,0,1,0

then its uv texture data
v,u,v
datauv 0,0,0
datauv 1,1,0
datauv 2,1,1

now to draw its face facing up

index 0,1,2

thats it

now if you wanted to flip the triangle so its only visible from under it you can simply counter clockwise the connection

index 2,1,0 is the other direction effectively switching the way its shown but you would also need to set your normals -1 on the y axis as well.

Quote: "but SoftMotion3D is the real master here "
lol i wouldnt say im the master at it but i do know how to make a model from scratch using code.
www.sheldonscreations.com
SoftMotion3D
AGK Developer
14
Years of Service
User Offline
Joined: 24th Aug 2005
Location: Calgary,Alberta
Posted: 5th Dec 2015 21:32 Edited at: 5th Dec 2015 21:54
ok agks primitive is using 4 triangles..... i dont know why because its a waist...
if you make a new primitive from another application it should just be 1 sided.

edit: i looked at the commands for memblock access and they suck....lol! i asked paul in the 2.15d thread if he has plans on adding the missing commands to really take control of 3d model making/editing. without access to the triangle face data or quad.... all you can do is modify an existing models uv data,vertex positions,normals. Doesnt look like you can do any triangle or quad face manipulation [ addition / deletion / or even any changes].

what i recommend doing is creating a new plain primitive with another application. it should only use 4 vertex positions.... much easier for you to code some manipulation to it.
www.sheldonscreations.com
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 5th Dec 2015 22:56 Edited at: 5th Dec 2015 22:59
I'm going to call this...

Chapter 1.3 - Making a Plain from Nothing

After digesting all of the suggestions and information about indexes (or indices, both are acceptable),I have come to the conclusion that the standard AppGameKit Plain is not adequate for my needs.

1. It has no indices. The plain is made up of 12 vertices. That is one for every corner of every triangle in the plain.
2. To move one corner of the Plain, I have to locate up to 4 vertices, and apply the same transformation to each
3. To change any other attribute of the plain, such as the normals or UV, the same process of finding up to 4 vertices must be followed
4. there is a large scope for error
5, I would assume that shaders and so forth will have the same laborious task as me, finding multiple vertices for one point on the plain.

The solution, therefore, seems to be to make my own. I tried making a Plain in Wings3D, which should theoretically be one of the simplest. It did not however prove to be a simplistic task, having to tessalate quads after rotating one face to align the resulting triangles. It seemed rather messy and lacking control. So I will resolve my dilemma by coding the Plain. Along the way, I'll make sure I can reuse the functionality to make more complex shapes.

Dispelling the myth
Firstly, a misunderstanding has crept in. It is possible to use indices in Memblock Meshes. The default AppGameKit plain does not have indices. But the memblocks facilitate the use of them.

Making a skeleton memblock mesh
To make the code reusable, I will tackle the challenge in 2 steps:

1. Create a function that builds a skeleton mesh memblock. This will accept parameters for the number of vertices and another for the number of indices. It will build a skeleton with 3 attributes: position, normals and UV coordinates
2.Create a function that makes a Plain mesh memblock. This will utilise the aforementioned function, and then finalise the mesh by setting the attribute values.

So the Plain configuration is like so, the numbers identifying the vertices



The Indices for the top are 3,1,0 and 3,2,1
The Indices for the bottom are 0,1,3 and 1,2,3

Here is the code. Firstly, the constants have been extended:



Next, the generic Function to create a skeleton mesh for any quantity of vertices and indices:



And finally the function to create a Plain mesh. this calls the previous function and then populates the required values:



The final note for this entry is that I have not yet tested of I only need one side of the Plain with culling disabled. I will look into this again later.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt

Attachments

Login to view attachments
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 6th Dec 2015 21:21 Edited at: 6th Dec 2015 21:21
Chapter 1.4 - Helper Functions

Now the basics are in place for making Meshes, I will be moving on to splines. But before I do, I created a set of helper functions for the mesh module. Part of modularisation is making sure you never have to access the raw data. If you need something, there should be a function to retrieve it. So here are a few functions, there will be more by the time I have finished.

Get Number of Vertices in Mesh

// ****************************************************
// Get Number of Indexes in Mesh
// ****************************************************
function getMeshIndexCount(meshId)

exitfunction gMesh[meshId].numIndices

endfunction 0

Get Position of Vertex


Set Position of Vertex


Get Vertex normals


Set Vertex normals


Get Vertex UVs


Set Vertex UVs


Get Indices
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
CJB
Valued Member
15
Years of Service
User Offline
Joined: 10th Feb 2004
Location: Essex, UK
Posted: 8th Dec 2015 02:25
Thanks for the functions! Nice to see some useful 3D stuff getting shared

I remember making a tunnel builder for a DB-Pro game I wrote some 12 years ago called STUN Fighter. In the level builder, you simply used the cursor keys to control a flight path (left/right roll, up/down pitch - elite style) and it built a tunnel mesh following your flight pattern. Normals were set to camera position (i.e. the centre of the tunnel) so they always faced inwards.

...I found the code! I was going to post it here, but it is DB-Pro, and it is truly horrible! Haha. Looking at it now, it would not help you at all anyway.
V2 T1 (Mostly)
Phone Tap!
Uzmadesign
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 8th Dec 2015 08:37
Sounds like it would make a good basis for a mobile game. You could position an invisible box ahead of the camera generating the tunnel that you have to navigate through.

Quote: " it would not help you at all anyway"


What would help is knowing how to set the normals. I know the theory, but my maths is terrible. I will know the 3D angle of each point on my spline, but need to work out the normal from that angle.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 16th Dec 2015 22:11 Edited at: 16th Dec 2015 22:14
Chapter 2.1 - Splines

The next component on the list is splines. A Spline is simply a line that starts at A, ends at B, and interpolates smoothly between the 2 points. At first this sounds exactly like a straight line. But imagine we set off from point A heading North. Point B is to our North East, and we want to be walking East when we arrive there. In order to do that, the most elegant option is to walk in an arc. It is better to imagine as an aeroplane taking the same course and it can only take sweeping movements, not sudden turns.

Here is a Bezier Spline of the type I am using:



There are different types of spline with different calculations, but the Bezier Spline is perfect for this task:

1. It is relatively simple to calculate
2. The handles allow the spline to be manipulated in a predictable manner.
3. It is easy to string multiple B-Splines together to make a more complicated track.

It is relatively simple to calculate
To make a B-spline you need 4 points, as detailed in the image above

1. Starting Point A
2. End Point B
3. Handle attached to point A
4. Handle Attached to Point B

The start and end points are self explanatory,
The handles describe the tangent at which you leave Point A, and the tangent at which you arrive at Point B. In our earlier example, this is how we describe leaving at a Northward heading, and arriving at an Eastward heading.
The length of the vector that connects the handle to the spline point also determines the shape of the spline. If you have a short vector, the line will turn quickly and more sharply towards the endpoint. A longer vector will create a slower, sweeping turn.
Likewise, the vector length at the endpoint will describe the final curve, short and swift or long and sweeping.
At some point in the middle, the control from Handle A diminishes while the control from Handle B increases. How the 2 handles are placed in relation to one another also influences the curve.

Finally, we need to make sure that when we connect 2 splines, the connecting point maintains the smooth curve. This is very easily achieved by rotating the previous handle B by 180 degrees so that the tangents formed are perfectly aligned.
The new Handle vector can have a different length to the previous one. In this way, the exit from the curve can be very different from the entry to the curve.

In the next post, I will show this in Code. It isn't as scary as it sounds!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 17th Dec 2015 09:59 Edited at: 17th Dec 2015 10:02
Chapter 2.2 - Spline calculations and code

Firstly, a spline is a concept. It doesn't actually exist anywhere, until you represent it graphically. Imagine trying to record the description of a wavy line, point by point, in a way that allows you to retrace the line later and follow its direction. It is going to take a lot of data!

At the fundamental level, we can store a bezier curve (our spline type of choice), as a set of parameters from which we can recalculate the curve:



As a quick visual reminder, this is what we are trying to create.



From these parameters, we can calculate any point on the spline. This is a very important point to understand. When working with splines, you decide whereabouts on the spline you want to be, and then perform a calculation to provide that point in 2D/3D space. It's a little bit like quantum physics, nothing exists until you observe it. Here is the array to store a 2D spline:



To calculate a point on the spline, the following polynomial coefficients are calculated. This is mathematical speak for something I do not need to understand, I am happy that the mechanics of this solution give me the result I need.




From this we can then calculate any Point in 2D space based on a time, t#. A is 0.0 on the spline and Point B is 1.0



This is the basics of bezier curve construction in 2D. The next step is to work out how to use this concept efficiently in the scenario of a never-ending track, and represent it visually.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
Van B
Moderator
17
Years of Service
User Offline
Joined: 8th Oct 2002
Location: Sunnyvale
Posted: 17th Dec 2015 15:27
Keep em coming Steve, there are plenty of people who'll find this stuff interesting and useful, if not now, then in a few months time when things like terrain systems start showing up.

It's great to see these new features in AppGameKit, makes it a real option to drop DBPro for most development.
SpecTre
Developer
16
Years of Service
User Offline
Joined: 24th Feb 2003
Location: UK
Posted: 17th Dec 2015 17:00
Quote: "Keep em coming Steve, there are plenty of people who'll find this stuff interesting and useful, if not now, then in a few months time when things like terrain systems start showing up."


+1, very useful and interesting. Great work BatVink.
The Amiga and Amos were great!
My website LEAP - Download Paint Pot here!
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 17th Dec 2015 18:45
Thanks for the encouragement guys. I'm ahead of what has been posted here, so I know there are more good things to post.
I already have a rudimentary rollercoaster, complete with first person ride.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 24th Dec 2015 11:12 Edited at: 24th Dec 2015 11:15
Chapter 2.3 - From 2D Splines to 3D Splines

This is a very short update to show the simple leap from 2D to 3D bezier curves. Repeating the code above but with an additional dimension, here is the Typed Array to store the 3D bezier curve parameters:



Here is the calculation of the polynomial coefficients:



And this is how we calculate the point in 3D space for a point in time between 0.0 and 1.0

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Quidquid latine dictum sit, altum sonatur
TutCity is being rebuilt

Login to post a reply

Server time is: 2019-10-16 21:32:19
Your offset time is: 2019-10-16 21:32:19