3D graphics using arrays?

  • The models already are in pretty much normalized coordinants of -1 to 1. Using color to define position probably has way too low of percision to be useful, not to mention it would be slow to constantly need to get the individual components.

    That's odd that using only one axis of rotation is that much faster. The rotation math is only done on three objects, one for each axis X,y and z. We could combine the equations together at the expense of being readable.

    The zsorting of the points is probably the slow point now. For the tilemap rendering we could instead do a zbuffer instead of sorting and see if that's faster. For the Sprite rendering we could import the normals and transform them too, and then don't display or sort the normals facing away from the camera.

    The tilemap object does some typically useful things when you set a tile, such as updating its collision polygons. That probably adds up the way we're using it.

    Overall 4000 points is pretty high and we probably can get something that looks good with much fewer. Although we'd want it much faster if at all possible.

    I did an animation test with that eagle where all the points lerp between two frames with distorted points. It only lost a few fps.

  • Have an idea that possibly could make it a lot faster. It's a pretty experimental approach to how we generally think of 3D. It would involve restructuring the point data, and have it indexed. I got the idea by looking at the way you get the point positions and the rgb value for those positions. Basically it would work like this...

    It's pretty much creating a search algorithm, only getting relevant data from the point cloud, limited to number number of "pixels" in the tilemap.

    Every cell of the tilemap just searches for a the color value it want's to show, and maybe we could get that directly from the point cloud if it was indexed. Translations and rotations would be done at Bounding box level for the object, so we don't need to reposition points individually.

    For a quick indexing test. You mentioned the data i pretty normalzed already, so we create 50 steps between -1 and 1. If we take the point cloud data, populate a 50x50x50 array with the average color of every point in each "cell". so if there is any point with the value 0,0,0 we would place the rgb value of that point in the dead center of the array. if a cell has no value, it means transparent, if has a value, it would render to the tilemap.

    If we can have some kind of bounding box representing the array data that we could rotate & transform A simple search from the each individual cell of the tile map looking at that bounding box, could get the indexed rgb rgb value of the cell it's looking at. For example. tilemap 25,25 is has the array cell # 26,25,12 (we can disregard all cells behind it as it is opaque)in it's view we would know what color to display for that individual pixel. If a tile map pixel is looking has multiple cells in it's view, we could get the average color of these, that way we could have something similar to anti-aliasing as well.

    LOL. hopefully you can understand what I'm rambling about. I'm going to do some tests indexing the point cloud data, so we can minimize the data we need to get. Theoretically you could have massive amounts of points, if you can get them quick enough from files on disk with an index, you probably wouldn't even need to load them in to memory.

    As long as each pixel know's what he's looking at, he could jump directly to the index point and get the color information from the correct "cell". the tile map cell is basically jumping straight in to "Column, 6, row 9, z 8, and getting the correct rgb value.

  • If we store RGBA in each cell we can get a bit more detail and antialiasing effect like this. We could store more information in this index, like surface direction, normal direction etc etc, but RGBA should do for now.

    Pic 1. If the ball fills only one tile, we can get the rgba value for the ball at index level 0. that's the average color and coverage of the entire ball.

    Pic 2. If the ball fills 2x2 tiles. we would get a semitransparent red shade from from each cell in index level 1.

    Pic 3. If the ball fills 8x8 tiles, we get the the rgba value from each cell in, index level 3.

    The only problem so far, is how we translate or rotate the object. Ideally we would rotate/translate a bounding box (or the index), instead of shifting all the points and values in the array creating a new index every tick.

  • R0J0hound

    Testing the indexing right now, and it seems to be working. We could potentially use an unlimited number of points in the point cloud. It doesn't really matter... it would take longer to build the index though, but once the index is built, we never really touch the points.

    Level 0 index. the average color and coverage of the shape. This is only used if the entire object fit in one "pixel" area.

    level 1 index. 2x2x2 array used when object fits in a 2x2 pixel area, and so on.....

    level 2 index. 4x4x4 array

    level 3 index. 8x8x8 array

    level 4 index. 16x16x16 array.

    level 5 index. 32x32x32 array. This is the maximum I've tested so far, and looks great on a 32x32 tilemap.

    you could go as high as your native screen resolution. 1920x1920x1920 for example. Ideally we could crop the away unused whitespace in the array so there's less area to search.

    Building the indexes is the easy part. Preferably we would have these prebuilt in a custom file, as the point cloud data is irrelevant once the indexes are built.

    I still have to figure out how to rotate the index. I'm an artist not a coder, so i can easily visualize what I'm trying to accomplish, but hard to do the actual syntax for it.

    Will share a capx once I'm done with the testing of building indexes.

    Although so far it seems performance is not based on how many points in the cloud (we could use millions) but rather the efficiency of the search algorithm (how fast per pixel we can get the rgb value from the index) and the actual render resolution.

    50x50 would be pretty fast, but 1200x1200 would be slower, unless we can optimize the search heavily.

  • That sounds similar to a SVO (sparse voxel octree) which is commonly used for rendering/storing voxels. Here's a link with some code to find the intersection of a ray and the octree that I may study a bit more later.

    http://stackoverflow.com/questions/1022 ... algorithms

    Right now we're just transforming all the points and basically rendering all of them. Next would be to just use a uniform 3d grid of voxels or a SVO and cast a ray for every pixel we want to display. Ray casting on a uniform grid could be done with a line drawing algorithm like dda. I'm uncertain it will be faster than what we're doing now, due to the overhead of events adding up and sometimes providing no gain. It may be interesting to try that approach, as it also would eliminate the holes on the model.

  • Yes a bit like that. But not really, as the position of a voxel is inferred based upon its position relative to other voxels. So we're don't really want to go the voxel route as it's too complex. My approach is indexing rgb values only in a grid, so we can get a 2d representation of a point cloud by searching the index, pixel by pixel.

    We only need an rgb value.

    How we search the index is where we can optimize a lot.

    Maybe some simple steps like this for the screen space index search could look like this ...pixel by pixel.

    1. is there any bounding box (index) in this pixel space.

    if no . carry on to next pixel, repeat step 1.

    if yes. get the name and the scale of the index. now we know which index to search. go to step two.

    2. search in z until we hit a point. (maybe we can do it like a ray caster/incremental or just search cell by cell)

    if no point is hit, carry on with next pixel. go to step 1.

    if we find a cell with an rgb value. Set this pixel to rgb value. Done,

    Proceed with next pixel. repeat step 1.

    Worst case scenario we need to repeat this the amount of pixels (resolution we want to render) for 100x100 would be 10.000 times.

    if we can render regular sprites we can render this... how fast we can search screen space and set rgb value is what matters. just like a regular 2d sprite moving across the screen we only need to draw one rgb value per pixel. we need to find the rgb value and draw it as quick as possible.

    possible? what do you think

  • I took a closer look at your example and group the events so i could see which was most cpu intensive.

    * The movement of all the points was by far the heaviest part at around 55% cpu usage. That's probably because they are moved individually...

    * The tilemap rendering was using around 35% cpu with draw calls of about 5% cpu.

    * Not using tilemap rendering z sorting was about 18% cpu, but draw calls at 35% cpu.

    I know these numbers are not always 100% accurate, but it gives us a hint of where to improve.

    The reason i got so high framerate before by only rotating in one axis, was because i rotated all the points as one entity. I did not need to calculate any new positions for them. I pinned them to a dummy sprite, and rotated the dummy sprite instead. Maybe somehow this could be done for each axis?

  • In your proposed algorithm step 1 requires sorting all the points into those bounding boxes, then in step 2 those would need to be sorted again by z. It would perhaps work well I you pre-calculated all of that but then you'd be stuck at one view angle.

    [quote:2cxp6ej9]The reason i got so high framerate before by only rotating in one axis, was because i rotated all the points as one entity. I did not need to calculate any new positions for them. I pinned them to a dummy sprite, and rotated the dummy sprite instead. Maybe somehow this could be done for each axis?

    That would only work for an xy rotation, if I understand it correctly.

  • R0J0hound here is an updated capx with my latest tweaks and explanations. I'm trying to shortlist the amount of data we need to show. Currently only the for each loop is the major slowdown. Is there any way to limit that? what would be nice in this case right now, would be a plugin you could feed the array data, and handles the for each loops, and renders. If you look at the capx, you will understand what I'm talking about. Commented in capx also.


  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • That pretty much just reduces the point count from 3991 to 328 which would give a speed increase. The model could always be made with a lower point count, and having the points uniformly spaced like that probably is preferred to the random sampling.

    That all could be done beforehand, and just use the rotation method we already have.


    I haven't done much work on the capx lately. I've been playing around with doing it in c and basic OpenGL to see the speed difference. 2% cpu vs 35% and it looks like I'm getting 60fps. Hmm, that was refreshing. Might try webgl and JavaScript next.

  • That sounds cool. Sorry i can't help you out in that case, I'm not much of a coder.

    I'm quite curious what the cpu and fps would be if you fill the entire screen with 1 point per pixel. Basically put a screen size box of points, distributed evenly, and have the rendering disregard any points that is not closest to "camera". That's just curiosity, what kind of load you would get.

    To explain little bit my reason for this whole thread, is that I've always missed a way to put simple 3D object in 2D games made in construct 2, without having to rely on something like Q3D plugin, when it's just small objects here and there. A way to load simple objects like coins, cards, UI elements, powerups, or whatever, because i want them rendered inline in small viewports (like your tilemap approach) so you can sort them Z-index wize along with regular 2D sprites. I don't know if it's possible or not, but that's what got me investigating what could be done, and so far, converting small objects to point cloud, seemed like a quite good approach, but maybe polygons are faster if you're using webgl/javascript, no idea. Instead of using tilemap, maybe something canvas or paster would be better?

  • I'll just cross post this for now:

    The approach is to render 3d with webgl to some other canvas and then copy it over to overwrite an object's existing texture. That's the cleanest way I've found so far to make it inline with other sprites.

  • I checked your post in the other thread and replied there. Fantastic work! If there is any easy way to turn this in to an easy plugin/behaviour for the C2 usebase, I'm happy to assist in any way I can, with tutorials, icons, artwork, models, and demo scenes.

    With background in 3D art, I can give some input of what designers might find useful in terms of simple settings.

    From what i saw so far, the only thing i would like to set is

    Light: angle / intensity / color maybe such things / ambience

    Model: Orientation.

    I don't know if any other animation support is included in the js, but for now, just simple objects like this is fine. Very useful for some level 3D level art, coins, powerups, UI elements etc etc...

    The next thing to wish for is some simple animation support for characters, but this is already way more than I hoped for...

  • A plugin would probably be the last step because that locks in a interface design and is more time consuming to develop from a few extra steps required.

    The code is mostly just raw webgl so it's pretty low level. Which means I'd have to build some way to have animation support. Probably means I'd have to make a loader for some file format with animation information.

  • I don't know if any other animation support is included in the js, but for now, just simple objects like this is fine. Very useful for some level 3D level art, coins, powerups, UI elements etc etc...

    This would be great for displaying things like field arrows as well. Awesome work, guys!

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)