First time here, I first want to thank you guys for making such a nice app
I just finished building my first Codea app, I wanted to make a little 3D renderer for fun, but I wasn’t expecting Codea to be so fast.
Edit: Think i’m nearly done with optimizing the code…Now hitting 36 fps in quality 2 on iPad 1 (that’s 4096 polygons or 12 288 vertices!)
update: Textures are up and running:
Video on shading:
Source: http://pastebin.com/i7P5wLmC (updated to shading)
Wow, that’s just awesome!
Tells you about Codea. That’s awsome. Code?
Hey there and thanks for the comments,
Regarding the code, I’m new to lua, so I’m sure people are going to mock me hehe
Seriously though, I want to clean it up and comment it before I share it. I’ll try to optimize it some more on my own too, but forums could actually be a pretty nice place for me to get insight on how to make it run faster…
I accept messy coders… You won’t be mocked… I promise.
Xavier that’s incredible. Do you mind if we show it off as a news item on the Codea main screen?
oh absolutely not, that would actually make me fell pretty good about myself heh
It’s 5 in the morning here in france, i’ll clean up the code tomorrow and post it before this WE Zoyt )
No problem @Xavier — I just meant the video, by the way.
This is awesome! You guys keep surprising me with what you’ve done with Codea. Try to remove the text. It might increase the frame rate a bit.
I want to see this code! You have far more vertices than I managed in my 3D viewer before I got a noticeable lag in the rendering - I want to see where the saving is.
Welcome to the community Xavier!
@Xavier - that’s incredible!
Do you have any link / reference to the Populous sphere trick from Glenn Corpes that you mention in the video? I had a quick Google but couldn’t find anything.
@Simeon - That’s what I figured, code section was aimed at Zoyt
@Andrew_Stacey - I’m nearly done cleaning up code, i’ll post an ugly version of it in a few minutes, hope you guys will help me improve it !
@frosty - here is the link to the post in question: http://glenncorpes.blogspot.com/2011/07/topia-landscape-finger-painting-and.html
His blog is pretty nice
Ok, here is the code.
Note that I am very new to lua, so don’t make fun I could really use all the help to clean it up and optimize it.
edit: code now on top comment
Feel free to ask if you have any questions,
thanks for heads up about being able to make a whole mesh with all the vertices Andrew, you were great help
Along with a few other tweaks, I now have it running at 40fps in quality 3 on iPad 1, it’s not 60 but it’s still very good.
Turning off z-ordering after at least one render pass gives you that pretty boost without losing too much quality
Code is updated. I’m sure i can still optimize it, going back to it
I would have imagined iPad2 to be even faster ^^
I’ve been looking for a way to handle texture parameters such as wrapping (and filtering), but I cannot find any info, so my guess is that it’s not implemented, correct ?
If it’s not possible in Codea, I was wondering if there was someone that could help me with “fixing” my problem
Let’s say, when you want to map your textures to a terrain built from a grid, you do something like this:
-- texture mapping
for z=0, mapSize, step do
for x=0, mapSize, step do
i = (x + z * (mapSize+step)/step)/step + 1
color_texCoords[i] = vec2( x/mapSize, y/mapSize )
detail_texCoords[i] = vec2( x/step, y/step)
Here I’m setting up the UV coordinates of two textures to be applied to the terrain:
The color map. It will be applied over the whole terrain using the UV formula for color_texCoords (like a big texture applied to the whole terrain).
This works fine with Codea because the resulting UV goes from 0.0 to 1.0, within the texture range.
The detail map. This is applied to every pair of triangles to give the impression of a more detailed texture up close.
My problem is that it won’t work with Codea because it’s impossible (or at least I can’t find the way) to set the texture parameters to “repeat”.
The resulting UV would go from 0.0 to 1.0 on the first tile, but then from 1.0 to 2.0 on the next and so on. Without “repeat”, this points to an area outside the texture and results in nothing being applied to the quad
My mind is not working right now and I cannot find a way to successfully make it repeat itself for every tile.
Anyone have an idea ?
This is a very nice piece of code, very cool idea
For the first time I saw the video, I thought you might have a lot of code. But, when I saw the code, it is not too long. It means that the Codea is great!
@Xavier Thank you for your fantastic code.
I am thinking that to render the simple objects such as a cube might not be too hard. However, I have to learn the 3D modelling a lot.
yeah, the principle is very easy, hence the code being pretty lightweight (Codea is indeed great though :))
All you need is a model (i generate a heightmap using perlin noise), which is nothing more than a bunch of vertices (points in 3D space).
However, if you want to your object to display properly, you need to use a list of indices to connect your points.
In the program, I use an array of triangles, and each contain 3 indices
-- basic structure
vertices = vec3( 0, 0, 10)
vertices = vec3(10, 10, 10)
vertices = vec3( 0, 10, 10)
polygon = vec3(1, 2, 3)
vertices[ faces.x ].z would then give me the z value of the first point in the triangle.
To render it on screen, you need to go through all the polygons and project each vertex onto the 2D screen.
The basic formula for that is x2D = x3D/z3D and y2D = y3D/z3D
The only real optimization I do is “cache” the projected points. This way, if the triangles are connected, i don’t have to recalculate the projection of the duplicated points.
That was a huge boost in rendering speed, but note that it is ideal in my case since i’m using a grid,
Initial comments on looking at the code:
I see you’re projecting from the origin onto the place z=1. That probably produces the fasted algorithm (computationally) for stereographic projection (though if you later add other things like transformations it can get complicated).
You’re removing back-facing triangles. This looks a little strange in wire-frame mode. I doubt that this produces a lot of saving in rendering the mesh as that’s pretty fast so the main saving here is that you don’t have to sort these faces. I’d test to see if this is an actual saving or not - the test to see whether or not to remove a face might actually take longer than sorting the faces.
Your formula for the distance of a face can be simplified. As you’re only using this for comparing faces, you don’t need to divide by 3:
x > y if and only if
3x > 3y, and you don’t need to square root the sum of squares: if
y are positive then
x > y if and only if
x^2 > y^2.
I wonder if it is possible to circumvent the sorting. Once you’ve computed the
f.dist, you know already where it fits into the scheme so simply insert it in the right place.
You’re resetting the mesh for every triangle. Again, you’d need to test this to see if this was actually faster, but I would have set up a table of all the vertices (arranged into triangles) and drawn the mesh all in one go. Indeed, I expected to see a huge saving between using the filled shape (ie using the mesh) and the wireframe (not using the mesh) but I don’t, so maybe if you draw the mesh once you’ll get a faster rendering.
On that, in wireframe mode then you could use the mesh. It might not look as good, but if you use a texture with three points and lines between them then this would render the wireframe using a mesh. That might be faster.
You could use
table.insert(obj,f) instead of
obj[poly] = f poly = poly + 1 and then drop
poly altogether. Similarly,
f.visible seems to do nothing: a face is visible if and only if it is in the
obj table and it is drawn if and only if it is in the
obj array, and the
obj array is reinitialised every draw.
All of these are just suggestions of where there might be savings. I’m no programmer and don’t know which actually save time or not, but are things that could be worth investigating.