Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 10:34 01 Aug 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : CMM2: API for 3D redering

Author Message
LeoNicolas

Guru

Joined: 07/10/2020
Location: Canada
Posts: 504
Posted: 03:58pm 07 Oct 2020
Copy link to clipboard 
Print this post

I'm creating an API for 3D rendering. For better performance probably I'll port it to CSUB on the final version.

In this example I'm rendering 5 objects at the same time

There is a lot of work to do.
What do you think about the API structure?

Video



The source code: https://github.com/.../colour.../blob/v0.3/api-3d.bas
Edited 2020-10-08 01:59 by LeoNicolas
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10310
Posted: 04:03pm 07 Oct 2020
Copy link to clipboard 
Print this post

Nice work - I was thinking about something similar but the bit you are missing and I couldn't work out how to do is handling hidden lines. Perversely this is much easier with solid objects (Painter's algorithm) than with wireframe.

Link to your code isn't working
 
qwerty823
Newbie

Joined: 30/07/2020
Location: United States
Posts: 30
Posted: 04:22pm 07 Oct 2020
Copy link to clipboard 
Print this post

IIRC (my 3d maths are a bit rusty), but if you compute the surface normal of the faces, and compute the dotproduct of that and the camera normal, any negative values are facing away from the camera and could be skipped in the drawing phase (backface culling).

This assumes no transparency in any of the faces (ie, wireframed faces are solid and not see through), which I assume is what you are after.

Also, looks like github link is here: https://github.com/leonicolas/colour-maximite-2-examples/blob/master/api-3d.bas
Edited 2020-10-08 02:24 by qwerty823
 
Sasquatch

Guru

Joined: 08/05/2020
Location: United States
Posts: 377
Posted: 04:42pm 07 Oct 2020
Copy link to clipboard 
Print this post

WOW! Very Cool!  And it looks fast enough to do "BattleZone" type games in pure MMBASIC!
-Carl
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 543
Posted: 06:55pm 07 Oct 2020
Copy link to clipboard 
Print this post

  qwerty823 said  IIRC (my 3d maths are a bit rusty), but if you compute the surface normal of the faces, and compute the dotproduct of that and the camera normal, any negative values are facing away from the camera and could be skipped in the drawing phase (backface culling).

This assumes no transparency in any of the faces (ie, wireframed faces are solid and not see through), which I assume is what you are after.
</a>


For information, I typed up some notes on how to do it on the Facebook page. I've pasted the info below.As mentioned, it works great for convex shapes with no overlapping faces, but the moment you need to obscure one surface with another it breaks down. However for a game like BattleZone this would be fine (there might be slight errors with the gun and the turret, but nothing major).

My code is here:
https://www.thebackshed.com/forum/ViewTopic.php?FID=16&TID=12868&fbclid=IwAR1Pl0gHcZrBW4UeZqyPjMeCTgHb6usO4IjzvgrE_xH1gaHWW5rFIEdH1nQ

The planes (i.e. surfaces) are made up of vertexes (points in 3D space).

So, the Vertex/point below is Vertex#0 and it is x=32,y=0,z=76
Defined in code as:
vertex(0,0)=32:vertex(0,1)=0:vertex(0,2)=76

A plane is defined as 3 or 4 vertexes. In the case below, plane 6 is made up from Vertex 5, Vertex 3 and Vertex 1.
Defined in code as:
plane(6,0)=5:plane(6,1)=3:plane(6,2)=1

The ordering is important. If you were to draw out this 3d model and you numbered each of the vertexes - when you look directly at that surface you would see that points 5, 3 and 1 appear in a clockwise rotation. It doesn't matter which point you start at, just the order in which they appear, so I could easily have defined this surface as point 3, 1 and 5, and it would still work fine.

The cross product is just a quick calculation that finds a vector pointing out from the plane. If we were to do this on the model and plot these cross product vectors, the model would look like a porcupine with vectors sticking out of each surface.

However, if you were to record the points the opposite way (anti/counter-clockwise) then you would have 1, 3, 5. This technically defines the same surface, however if you calculate the cross product of this plane, the vector would point in towards the center of the model.

This is why I say the order in which you use the vertexes to create the plane is important.

So, we have this cross product vector for every plane. In my program, x is horizontal, y is vertical and z is into and out of the screen (depth).... i.e. z is either facing towards the viewer or away.

If you imagine this vector sticking out at right angles from each of the planes.
If the Z part of the vector is positive, then this cross product vector is pointing towards the viewer (i.e. the surface is visible). If it is negative, then it is pointing away from the viewer (and therefore the surface must be hidden/behind the rest of the object). Think of a plane facing you with a vector coming out at right angles. As you rotate it around, the moment the Z part of that vector passes through 0 and into the negative, the face has effectively turned away from you.

This is one of the tricky concepts. We are used to 3d shapes being solid, but using this method we can have weird shapes were some parts of an object are only visible when facing the viewer. For my Elite ship, it only looks solid because we have a complete ring of surfaces which all connect seamlessly. If you remove one of those surfaces, you will not see the surfaces behind it, because they are pointing away from the viewer. You will just get a gap in the image.

So, the final step is just to work out what the cross product is. Well, it's a pretty straightforward calculation.

We need two vectors from the plane to calculate the cross product. To use the above example, where plane/surface 6 was made up of points/vertexes 5, 3 and 1. Given that a vector is simply the distance between two points. Vector1 is the difference between points 5 and 3 and vector 2 is the difference between points 5 and 1.

Given two vectors vector1 and vector 2 (i.e. 3 points on a plane), we use the following formula.
If Vector 1 is defined as (dx1,dy1,dz1)
and Vector 2 is (dx2,dy2,dz2)
then
crossX=dy1*dz2-dz1*dy2
crossY=dz1*dx2-dx1*dz2
crossZ=dx1*dy2-dy1*dx2

Which means the final cross product vector is defined as (crossX,crossY,crossZ).
Of course, because we only actually care about the Z part of the vector, we don't need to calculate the first two parts.

IF CrossZ > 0 then we plot it because it is facing the viewer. If it is negative, we do not plot it.

Does any of that help clarify what I'm doing?
Edited 2020-10-08 04:56 by PeteCotton
 
LeoNicolas

Guru

Joined: 07/10/2020
Location: Canada
Posts: 504
Posted: 07:18pm 07 Oct 2020
Copy link to clipboard 
Print this post

I'm sorry for the source link...

This is the correct link:

https://github.com/leonicolas/colour-maximite-2-examples/blob/v0.3/api-3d.bas

I'm using the tag link instead the direct source link.

I'm posting this project here because it was restricted only to the CMM2 Facebook page.

I'll implement in a future version a hidden faces algorithm, but for the current source state I'm trying adding more features and fix the current issues. I need to fix the translate x rotate center issue and I would like to add the object scale sub routine.

Pette Cotton is help me with the hidden faces algorithm.

We are thinking to port Elite game to the CMM2 and a wire frame 3D API is enough to do it I guess. Does Elite use solid objects or only wire frames?
Edited 2020-10-08 05:22 by LeoNicolas
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 543
Posted: 07:53pm 07 Oct 2020
Copy link to clipboard 
Print this post

  LeoNicolas said  
We are thinking to port Elite game to the CMM2 and a wire frame 3D API is enough to do it I guess. Does Elite use solid objects or only wire frames?


The original 8-bit Elite were all wireframe with hidden line removal. The 16 bit ones were filled surfaces.
 
mkopack73
Senior Member

Joined: 03/07/2020
Location: United States
Posts: 261
Posted: 11:46pm 07 Oct 2020
Copy link to clipboard 
Print this post

There's also a number of other things graphically for Elite (the Radar for example). But this is a hell of a good start... If you guys are interested in working together on the Elite port, I'm certainly interested in collaborating. There's a LOT to work on! The graphics engine is almost the most straightforward (these days at least).
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 543
Posted: 12:31am 08 Oct 2020
Copy link to clipboard 
Print this post

There is a C conversion of Elite here that might help.

https://github.com/fesh0r/newkind

They converted it from the original Elite assembler. Looking at the graphics routines they have simplified them and removed a number of "tricks" the 8 bit micros used (such as reflecting mirrored points) in favour of easier to understand routines. But a lot of the stuff like Galaxy generation and trade goods are all a great place to start for those sections.
 
mkopack73
Senior Member

Joined: 03/07/2020
Location: United States
Posts: 261
Posted: 12:52am 08 Oct 2020
Copy link to clipboard 
Print this post

  PeteCotton said  There is a C conversion of Elite here that might help.

https://github.com/fesh0r/newkind

They converted it from the original Elite assembler. Looking at the graphics routines they have simplified them and removed a number of "tricks" the 8 bit micros used (such as reflecting mirrored points) in favour of easier to understand routines. But a lot of the stuff like Galaxy generation and trade goods are all a great place to start for those sections.


Yeah I tried to look through the original code but it was a nightmare since I'm not very good at 6502 assembly, even with all the comments. I suspect this C code is MUCH more understandable since it'll follow normal structured code concepts. Just hope they didn't use "Structs" too much since we don't have that sort of capability in MMBasic.
 
LeoNicolas

Guru

Joined: 07/10/2020
Location: Canada
Posts: 504
Posted: 01:14am 08 Oct 2020
Copy link to clipboard 
Print this post

Yep, the lack of structs on basic difficult our job . To reproduce this functionality we need to use variables following a naming convention... it's not good.

Maybe in a near future we will have struct variables on MMBasic  
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4311
Posted: 09:03am 08 Oct 2020
Copy link to clipboard 
Print this post

  LeoNicolas said  Yep, the lack of structs on basic difficult our job . To reproduce this functionality we need to use variables following a naming convention... it's not good.

Maybe in a near future we will have struct variables on MMBasic  


I think that highly unlikely.

I'm fairly certain it is possible to write a pre-processor that would take a STRUCT definition and automatically convert it into a set of variables and BASIC accessor functions, though the result would not necessarily be pretty or optimal.

Best regards,

Tom
MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
RetroJoe

Senior Member

Joined: 06/08/2020
Location: Canada
Posts: 290
Posted: 03:52pm 08 Oct 2020
Copy link to clipboard 
Print this post

@LeoNicolas - nice work! I sense a BattleZone clone in our future :)

I sent you a private message (accessible near the top-left of The Back Shed home page, third item down). Hope you have some time to take a look.

Cheers,

Joe P.
Enjoy Every Sandwich / Joe P.
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 543
Posted: 04:27pm 08 Oct 2020
Copy link to clipboard 
Print this post

  thwill said  
I'm fairly certain it is possible to write a pre-processor that would take a STRUCT definition and automatically convert it into a set of variables and BASIC accessor functions, though the result would not necessarily be pretty or optimal.

Best regards,

Tom


I think this is an awesome idea. It would be quite straightforward to write a prgram which read the Elite C code and stripped out some of the structures and produced an Basic header definition and a corresponding text document which described what they are. You might even be able to write a program which ocnverted the majority of the C to Basic, however it would still need a fair bit of manualy massaging to make it actually run I suspect (variable scope springs to mind straight off the bat).
Edited 2020-10-09 02:28 by PeteCotton
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 543
Posted: 04:30pm 08 Oct 2020
Copy link to clipboard 
Print this post

But to be honest - maybe most of the fun is in atually re-writing the program from scratch and seeing how optimised we could make a MBasic one.
 
LeoNicolas

Guru

Joined: 07/10/2020
Location: Canada
Posts: 504
Posted: 04:39pm 08 Oct 2020
Copy link to clipboard 
Print this post

I agree with Pete. It'll be fun to rewrite it in MMBasic keeping a reasonable performance.

For 3D drawing I'll need to use CSUBs due the high number of loops I need to perform to draw the objects or to calculate the normals and hidden faces.

Yesterday I created my first CSUB routine and it worked like a charm
 
MauroXavier
Guru

Joined: 06/03/2016
Location: Brazil
Posts: 303
Posted: 11:27am 09 Oct 2020
Copy link to clipboard 
Print this post

  PeteCotton said  But to be honest - maybe most of the fun is in actually re-writing the program from scratch and seeing how optimized we could make a MBasic one.

For me is very tempting to use CSUB to have a severe speed up in my current project (is a secret yet), but I agree with PeteCotton, I think there is no fun if I use CSUB.

Most of the fun is to make a 100% MMBasic game to run at a reasonable speed with impressive results.

I'm can't talk for others, but as I'm talking just for me and for what I do, I think that using CSUB with break my necessity of the "challenge well done" feeling.

Anyone can make any use of CSUB as they wish, I'm not saying that the use of CSUB is like a "cheat", I mean that this put the program in other categories, like a " program not done 100% in MMBasic", what breaks my "personal rules of fun".
Edited 2020-10-09 21:29 by MauroXavier
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4311
Posted: 12:18pm 09 Oct 2020
Copy link to clipboard 
Print this post

  PeteCotton said  But to be honest - maybe most of the fun is in atually re-writing the program from scratch and seeing how optimised we could make a MBasic one.


Assuming that is with reference to my STRUCT preprocessor idea I wasn't specifically thinking of using for converting C-structs, I was thinking of it as an extension to MMBasic achieved via the use of a preprocessor. Obviously whilst such an approach allows you to extend the language it has the major disadvantage that you lose the immediacy of running MMBasic ... it is akin to creating a compiler where the source is MMBasicExtended and the "machine-language" is regular MMBasic.

Anyway, just an idea, not something I need or intend to pursue at the moment.

Best wishes,

Tom
Edited 2020-10-09 22:52 by thwill
MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 543
Posted: 04:26pm 09 Oct 2020
Copy link to clipboard 
Print this post

  MauroXavier said  
  PeteCotton said  But to be honest - maybe most of the fun is in actually re-writing the program from scratch and seeing how optimized we could make a MBasic one.

For me is very tempting to use CSUB to have a severe speed up in my current project (is a secret yet), but I agree with PeteCotton, I think there is no fun if I use CSUB.

Most of the fun is to make a 100% MMBasic game to run at a reasonable speed with impressive results.

I'm can't talk for others, but as I'm talking just for me and for what I do, I think that using CSUB with break my necessity of the "challenge well done" feeling.

Anyone can make any use of CSUB as they wish, I'm not saying that the use of CSUB is like a "cheat", I mean that this put the program in other categories, like a " program not done 100% in MMBasic", what breaks my "personal rules of fun".

Mauro, this sums up my thinking exactly. I have no problem with other people using CSUBs, but for me I'm really trying to push the limits of my BASIC programs. I am very comfortable with C (my daily job is a C and C# programmer), but I just want to push myself and see what problems I can solve without resorting to brute force subroutines. Of course, one could argue that all of the BASIC command words such as Blit are just CSUB's in a different name, and that is fair, but this is a personal challenge. My current project is really giving me some serious problems. I could fix them in a heartbeat with a single CSUB, but if I do that, then why wouldn't I just make the game in Unity on a full blown PC?

Again, I'm not judging anyone for using CSUBs, this is simply a personal challenge that I am thoroughly enjoying.


  thwill said  
  PeteCotton said  But to be honest - maybe most of the fun is in atually re-writing the program from scratch and seeing how optimised we could make a MBasic one.


Assuming that is with reference to my STRUCT preprocessor idea I wasn't specifically thinking of using for converting C-structs, ...


I wasn't really aiming it directly at anything. As I mentioned above, I think everybody is getting different types of enjoyment out of the CMM2. If you write Elite using CSUB's it will in no way lessen my enjoyment of playing it, or my appreciation of the amount of work you would have put in to writing it. I'm loving getting down and dirty with the CMM2 - I still can't explain why. But I think part of it might be the fact that it feels like the hobbiest scene of the 70's and 80's, where people were more interested in making something cool rather than making money. Part of that fun is the diversity of approaches we all bring to these projects. Conversations like this about making Elite or Battlezone on this hardware are themselves exciting. I would hate it to become a place of judgement about people doing it the right way or the wrong way....  
 
LeoNicolas

Guru

Joined: 07/10/2020
Location: Canada
Posts: 504
Posted: 06:14pm 09 Oct 2020
Copy link to clipboard 
Print this post

I'm writing the 3D API in Basic and I'll do it in CSUB's too, and I would like to keep the compatibility between both. We will be able to swap between them, only changing the included file.

For the Elite port, it will be great writing the game logic in Basic and maybe keep the rendering routines (the 3D engine) using CSUB's, but having both versions, we can also use it Basic version.
Edited 2020-10-10 04:15 by LeoNicolas
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025