3D engine... Much interest?

Right. I’ve broken off from the usual workload this weekend, to start work on something I’ve been itching to get stuck into for a while now. A 3D engine for Corona!

The results are crude so far. Cubes can be created at any x,y,z world co-ordinate and they’re rendered in perspective, but that’s pretty much it. The renderer doesn’t yet skip faces that aren’t facing towards the camera or that would be rendered off-screen, there are no other shapes yet, no support for importing models, no lighting, no rotations, no ability to move the camera around, no UV mapping, and so on. The current state is more a proof of concept to myself, that this could work.

There’s a lot still to do and of course, existing frameworks for the job. So before I spend too much of my time prioritising further work on this over billed projects, could I just get a bit of insight please, as to whether this is something many Corona developers would be interested in?

The goal is the same as with Qiso. Lightweight, performance optimised rendering, and ease of use. It’s pure Lua so platform independent and like with Qiso, it’ll be possible to draw standard display objects above the render.

Any thoughts at all, please shout out.

1 Like

I think is very very cool and would love to see the progress. That being said, I am not into making 3D games so I would probably never use it. Now Qiso I have big plans.

I doubt you will get anything performant unless you use C.  But I can see a use case for something like Unity-lite.

I did promote this to Corona a while ago but no dice there.

I’m still not far enough through to be able to say much more than “it seems to work”, but… It does seem to work =).

I don’t have normals implemented yet and my face culling will be dependant on that, so currently it’s drawing absolutely everything which means that my 5 test cubes are effectively resulting in a 60 polygon render… Nothing to write home about but 60 poly behaves perfectly fine at the moment.

That said, there’s no lighting or UV mapping yet either, which will of course add to the processing work and impact performance… Only one way to find out though!

Cube is only 6 faces. Try with circle or torus?

take a hardware 3d core (GLES) and turn it into a low-level ortho-billboard 2d engine (Corona)

then re-implement pseudo*-3d on top of that in high-level interpreted script (yours)

potentially interesting for “effects”, like rolling a die, but not likely to be of general use

(*have you tried texture mapping?  2d deform of uv does not equal perspective-correct)

(@SGS - i’d assume his count is of triangles)

I disagree @dave… There are plenty of simple 3D games that would be easy to implement if a basic 3D engine was involved.

Think games like helix jump for example. Low poly count and simple geometric shapes.

I don’t think volumetric shading, fogging or complicated ray tracing is needed for hyper casual gaming.

would depend on performance…  count up helix jump’s on-screen floors * wedges * triangles to estimate load, fe very roughly:  6 floors * 30-gon * 4 tris ~= 720.

[added] it’d maybe start getting feasible if capable of ~1000 tris/frame at no more than 25% cpu load, as a ballpark

First things first, in case this wasn’t your “existing frameworks”: SceneKit

Back to implementation details, face culling is one thing, but once you have objects (or more accurately, regions of objects) competing for who’s in front, you’ll need to deal with hidden surface removal. For mostly static scenes BSP might work, but if instead you opt for a depth buffer you’ll suddenly have a HUGE number of reads and writes to memory, which also happen to have less than ideal branch and locality characteristics for good measure. Not an “it won’t work” thing, but major performance issues await.

There was some relevant discussion in the roadmap threads earlier this year.

As alluded to there, I had something based on external textures working for one object. It’s somewhere along the way to more, but I haven’t had a chance to do much with it lately. (In a similar way I’ve putzed around with qu3e and nudge, but would probably just go all the way with say Bullet now.) Let me know if you want to see any of this, as I’m leaning toward moving on to another approach *.

As far as importing goes, Stefano Trettel has an Assimp binding. I’m not sure how 5.3-ish the Lua code actually is, but if not too much then that seems a good way to go.

* - Once the source is made available I intend to look into implementing a proposal of mine. (Feedback welcome!) There is the notorious problem, also affecting Scott’s plugin, of objects effectively being forced to draw on top of the hierarchy. I still believe stitching proxy objects like so, which interact with the timing of display objects, would be a fairly non-intrusive means of opening this up somewhat. As mentioned in the examples, a 3D scene could be one such object. On the other hand, it could be more lightweight, say two objects that enable and then disable a flag respectively, before and after a soup of polygons you maintain on the Lua side:

local group = display.newGroup() local scene = AWESOME3DPLUGIN.NewScene() group:insert(scene)

or

local group = display.newGroup() local soup = display.newGroup() soup:AddPolygon(1, 2, 3, 4, 5, 6, 7, 8, 9) -- triangle with (1, 2, 3), (4, 5, 6), (7, 8, 9) -- and so on... group:insert(AWESOME3DPLUGIN.EnableDepthBuffer) -- precedes triangle soup... group:insert(soup) -- ...render group... group:insert(AWESOME3DPLUGIN.DisableDepthBuffer) -- ...follows soup

I’m not sure where to start, so apologies if I miss any answers out here…

@SGS & @davebollinger Yep, counting triangles. I haven’t tried other shapes yet, simply because I haven’t yet built functions to map out the vertices of other shapes, nor have I built functions to import objects (.obj files are plain text so easy to import, and Blender can output them so I’m aiming to support those).

Ref texture mapping… In lieu of any real lighting support and because I haven’t done UV mapping yet, I’m currently drawing faces in a randomly generated colour, so no, I’ve no texture mapping to benchmark yet. I’m hoping that the way Corona loads textures in to memory once when used multiple times will help with that.

It’s definitely too early to give promises, or real performance results, but I learned a lot about performance in both Lua and Corona when building Qiso and am translating a lot of that into this engine. It might not work - I’m asking a lot from any language that isn’t ASM really, but I’ve got enough working now to know that at least the basics are possible in Corona without performance impact. Even if I end up with something that just allows the occasional 3D model to be loaded in and rendered with real-time modifications I’ll probably be content. I mean, I’m certainly not expecting to pull off the next Witcher game.

@StarCrunch I’m wanting this to be platform independent so SceneKit wouldn’t be an option here.

Currently I’m looping through the created objects and in turn through the faces of those objects to render, which is wrong. The end result will actually be to loop through all of the faces that would be within view of the camera, independently of the objects they belong to, rendering them in order of their z instead. This way it’ll organically only matter which face is above which other face, rather than entire objects appearing over other objects. This still of course leaves the problem of intersecting faces though, and I must admit that’s something I don’t yet have an answer to that doesn’t rely on real-time masking which is just too slow.

Demo so far…

http://development.qweb.co.uk/test/

This looks cool. I mean really cool. I’m just not sure what use I would have for it or how I could use it. Have you thought of some practical implications for it within the Corona environment?

To be honest, not yet, no. I usually build these things as and when we have a need for them, but this time it’s more of an itch that needs scratching.

Scratch that itch

Second, slightly cooler demo although it doesn’t show everything that works so far: https://development.qweb.co.uk/test2/

  • Objects can be moved and rotated along x,y,z axis

  • Camera can be moved and rotated along x,y,z axis

  • Rendering now properly iterates each face, (rather than each object then face). Faces are now therefore rendered in order of distance from the camera… Although if I’m honest, the face distance is currently just the object distance… I need to figure out the proper face ‘middle’ by averaging the vertices that it’s built from…)

  • Face normals are used to determine whether the face is pointing towards the camera or not, and any that aren’t are ignored by the renderer

Still to do before this is actually useful to anybody:

  • Proper colour and texture support. Currently each face is just given a random shade of white.

  • Needs to handle intersecting faces. Currently the rendering order isn’t enough to work properly if two objects are placed in a way where their faces morph together. I’m brewing an idea of splitting faces up on-the-fly where intersections happen so that the resulting pseudo faces can be rendered separately, but this is probably too much processing work to pull off in Corona, and I’ve a feeling it’d screw up the texture mapping… My thinking-hat is still on for this one.

  • Lighting. I’m not yet sure if Corona will be able to pull off anything too fancy for this - it’d be nice to have a full-on vertex-normals based smooth lighting effects, but I’d be happy enough if I can make old-school per-face lighting work to be honest. For now at least. Unlikely to have proper ray-casted shadows etc any time soon.

  • Camera lock support. I’ll be adding functions to lock the camera to face a particular object or x,y,z location so that as it or the object is moved around, camera rotation calculates itself. This’d make cut-scenes really easy to script.

  • Camera follow support. I’ll be adding functions to lock the camera to move with a particular object, so that as the object is moved around, the camera moves with it. This combined with rotation lock would make third person view games really easy too.

For now though, I may have to leave it as-is for a while. I’ve scratched a fair amount of this itch now, but really need to crack on with billed projects!

As I mentioned above, this is genuinely hard.  :slight_smile: And unfortunately, in an uncontrolled environment, you will run into it.

Read up on binary space partitions, if you haven’t already; from your comments, it sounds like you’re halfway there. This technique would be totally valid, for instance, where you’re traversing static geometry most of the time and can overlay graphics on top, as a one-time startup cost per scene.

Thanks, I’ll look into that. I understand binary modifiers in terms of 3D modelling, but coming at it from the side of the renderer is a whole other story!

Final test before I call it a night - quickly playing with UV mapping: https://development.qweb.co.uk/test3/ Seems to perform well enough so far!

re uv:  try using a checkerboard instead of a pacman (as it’s harder to judge distorted ellipses against each other).  then set up your cube/camera such that camera is “just above edge-on” to the cube’s top face - such that far edge of top face appears to significantly recede due to perspective (it should appear distinctly trapezoidal).  now ask:  are the checker rows evenly spaced in screen-space (incorrect) or do they get progressively “scrunched up” as they recede into perspective (correct)?

The HTML render isn’t the best quality really. In the simulator the effect is much cleaner. I’ll do a checkerboard version tomorrow and maybe an Android APK demo and/or a video though.

I’m actually finding it pretty difficult to put this project down now, I must admit. The result so far is perhaps better than I was expecting. Equally though I’m now hideously behind on everything else!

I know you hate it when I say it but this looks perfect for some big box voxels.