![]() |
Forum Index : Microcontroller and PC projects : CMM2: API for 3D redering
Author | Message | ||||
LeoNicolas![]() Guru ![]() Joined: 07/10/2020 Location: CanadaPosts: 504 |
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 KingdomPosts: 10310 |
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 StatesPosts: 30 |
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 StatesPosts: 377 |
WOW! Very Cool! And it looks fast enough to do "BattleZone" type games in pure MMBASIC! -Carl |
||||
PeteCotton![]() Guru ![]() Joined: 13/08/2020 Location: CanadaPosts: 543 |
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: CanadaPosts: 504 |
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: CanadaPosts: 543 |
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 StatesPosts: 261 |
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: CanadaPosts: 543 |
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 StatesPosts: 261 |
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: CanadaPosts: 504 |
Yep, the lack of structs on basic difficult our job ![]() Maybe in a near future we will have struct variables on MMBasic ![]() |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
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: CanadaPosts: 290 |
@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: CanadaPosts: 543 |
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: CanadaPosts: 543 |
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: CanadaPosts: 504 |
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: BrazilPosts: 303 |
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 KingdomPosts: 4311 |
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: CanadaPosts: 543 |
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. 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: CanadaPosts: 504 |
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 |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |