Instancing Multiple Objects Lowers Framerate of WEBGL Application - javascript

I am developing a THREE.JS WebGL application where I need to render multiple objects with the same geometry and I've stumbled upon a bottleneck. It seems that my instancing of objects has some issue, that I can't really understand/realize, maybe someone can help me with that. For context, I have a PointCloud with normals, that gives me information about where to position my instanced objects, and also the orientation of the object through the normal quaternion. Then, I loop through this array, and place each instanced object accordingly. After looking at various posts about instancing, merging, etc, I can't figure out what I'm doing wrong.
I attach the code snippet of the method in question :
bitbucket.org/snippets/electricganesha/Mdddz
After reviewing it multiple times, I'm really wondering what is wrong here, and why does this particular method slow down my application from 60fps to 20fps.

You might be overcompensating with the optimization.
In your loop where you merge all these geometries try to add something like this
var maxVerts = 1 << 16;
//if merging a new object causes the vert number to go over 2^16 push the merged geometry somewhere, and make a new one for the next batch
if( singleGeometry.vertices.length + newObject.geometry.vertices.length > maxVerts ){
scene.add(singleGeometry);
singleGeometry = new Geometry();
}
singleGeometry.merge(newObject.geometry, newObject.matrix);

Related

Parse shape movement from createjs tween?

I'm trying to pre-calculate the bounding boxes of objects in a createjs file.
I have a simple recursive loop that loops over the tween.
I'm having trouble understanding how the data is stored.
My understanding is so far:
tween._stephead - the start of the tween
tween._stephead.next - the next tween target, with multiple .next objects
and mixed in between there seem to be some ease objects.
For each of the tween targets, I read the props, and move the bounding box of my shape according to the values x and y.
This seems to work okay for single objects on a tween, but as soon as there are multiple objects in a tween, this falls apart, due to the fact that its stored in an array, and objects not in the array are still visible on screen.
Ive looked over the API and haven't found any other way to do pre-calculation of objects movements... Am I going about this right?
I ended up using a simpler method, just play the demo though without displaying it to the user.
for (var f=0; f<totalFrames; f++) {
stage.update();
var c = exportRoot.numChildren;
while(c--) {
var child = exportRoot.children[c];
...
}
}

Three.js: how to force update matrix after cloning? (to use with CSG ThreeBSP)

I'm trying to clone and then scale a mesh, but scaling does not seem to be working immediately on the cloned object, for programming purposes using CSG ThreeBSP. I think I should call a function after the scaling to force the matrix or other internal variables to recalculate immediately and not to wait for the full update loop on render side.
My code looks something like this:
var someMesh2 = someMesh1.clone();
someMesh2.scale.set(2,2,2);
someProgrammingOperation(someMesh2);
//It turns out that internally, someMesh2 still has the same properties (matrix?) as someMesh1 :(
What am I missing? Suggestions are also welcomed :)
object.matrix is updated for you by the renderer whenever you call renderer.render().
If you need to update the object matrix manually, call
object.updateMatrix();
and it will update the matrix from the current values of object.position, object.quaternion, and object.scale.
(Note that object.rotation and object.quaternion remain synchronized. When you update one, the other updates automatically.)
three.js r.84
In the end, my problem was that the CSG ThreeBSP object needed to work based on the Geometry of the object, not in the Mesh itself. I applied the scaling on the Geometry and it worked as expected.
There is a caveat though, that one should be careful as with the meshes and geometries instances, therefore is needed to do some cloning in order to keep the original objects as they were, as in the following example:
var clonedMesh = original.mesh.clone()
var clonedGeometry = clonedMesh.geometry.clone()
clonedMesh.geometry = clonedGeometry
clonedMesh.geometry.scale(2,2,2)
var someBsp = new ThreeBSP( clonedMesh )
var newMesh = someBspBsp.toMesh()
someScene.add newMesh

Three JS and Maya: exporting just the animation as JSON

I've an animated model that I've animated with Mixamo and then exported as an FBX into Maya. I've then used the Three.js exporter to output the animation 'baked' as morph targets.
Here's how the model looks when loaded into Maya:
However, when I read the data in, it includes not just the animation, but also the base model in a static pose, and each morphTarget array has the vertices repeated in it. This is what it ends up looking like:
Beyond manually writing some code to de-duplicate the vertices, is there any way to just get the animation out and not the model as well? I'm very new to Maya, so I'm guessing there's an option that I need to untick, or some selection step that I'm missing.
Thanks in advance
Should someone else have this problem, there's a simple answer (at least in this instance) - truncate the vertex and face arrays by half. After checking the vertices for duplicates it turned out they were all in the second half of these arrays, and could just be dumped.
geometry.vertices.length = geometry.vertices.length / 2
geometry.faces.length = geometry.faces.length / 2
geometry.morphTargets.forEach(function(target) {
target.vertices.length = target.vertices.length / 2
})
There's almost certainly a better way of doing it however.

HTML5 - Collisions [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I'm working on a top down game, and this game is going to contain a lot of collisions simple and complex.
After doing some research, I understand that I have to always compare my character with 'object' within my code - and then check for collision calculations.
EG:
CheckCollisions(Player, Object);
Which means I have to add in every single collide-able object within my scene, into my code:
CheckCollisions(Player, Building1);
CheckCollisions(Player, Building2);
CheckCollisions(Player, Trash);
CheckCollisions(Player, Bench1);
CheckCollisions(Player, Bench2);
CheckCollisions(Player, Office1);
CheckCollisions(Player, Office2);
First off, my objects might not even be simple rects, they might be complex shapes. Secondly, some of them might have their own rotation. And thirdly, what happens if I have over tens of thousands of collie-able objects in my scene?
Ins't there an easier way to check for collisions within a HTML5/JS game?
Is this even possible? I'm really just looking for some advice and pointers.
Thanks
It's very uncommon to have a named variable for every single object in your game. Usually you store all objects in one data structure (like an array) and when you need to do something with all objects, you do a for-loop over this array.
Some important objects, like the player character, could have an own variable, but they should also be in the "all objects" array, so you don't need to program a special handling to include the player character.
Regarding performance: When you check everything against everything, the amount of collision checks which need to be performed increases quadratically. But you can reduce the effort when you only check collisions of those objects which are already close to each other. Before you check collisions, you:
divide the playing field into rectangular zones (the zones must be at least as large as the largest object).
Then you assign each object to the zone its upper-left corner is in.
Then you take each zone, and check collisions of each object in it with the other objects in the zone and with all objects the three zones right, down and rightdown from it (for objects which overlap zone borders).
When you have very complex shapes, you could also speed up collision-detection by calculating a bounding-rectangle for each shape (the smallest possible rectangle it fits into). Before you check the collision between two objects, you first check if their bounding rectangles intersect. When they don't, there is no chance for the complex shapes to intersect, and you can skip all the complex calculations.
As everyone so far has indicated, an array of objects is much better than naming all your objects individually.
A much easier method of collision detection that might work for you is to have a central object that tracks all occupied spaces. For instance, let's call it LocationTracker for now.
Assuming you're only using x and y axes, you can have a Point object that stores an X and a Y location, (and if you want to get fancy, a timestamp). Each object as it moves would send an array of all the Points that it is occupying. For example, you can call locationTracker.occupySpace(player[i], array(point(3,4), point(4,4), point(5,4)), etc.
If your call to occupySpace returns false, none of the Points match and you're safe, if it returns true, then you have a collision.
The nice thing about doing it this way is if you have x amount of objects, instead of checking x*x times per move, you check x times max.
You wouldn't need to pass in all points of the objects, just the outer most ones.
1 - you don't need to write a line of code for every object in your game. Put them into an array and loop over the array:
var collidableObjects = [Building1, Building2, Trash, Bench1, Bench2,Office1, Office2];
var CheckAllCollisions = function() {
for (var i=0; i<collidableObjects.length; i++) {
CheckCollisions(Player, collidableObjects[i]);
}
}
2 - if you have complicated collision check (ie rotated shape, polygon, etc) you can first check a simple rectangle check (or radius check) and do the more accurate check if the first one returns true.
3 - if you plan to have tens of thousands of objects you should have smarter data collections, for example objects sorted by X coordinate so you can quickly avoid checking everything larger than Player.X+100 and smaller than Player.X-100 (using binary search), or split the objects into a grid and just check the objects in the 3x3 grid cells around the player.
A much better way is to put all your scene objects into an array or a tree structure and then
for( var i=0; i<scene.length; i++ ) {
scene[i].checkCollision( player );
}
if you add a function .checkCollision() to every object, you can handle any special case in there.
It's a good idea to make the player a rectangle so the checking code doesn't become too complex.
Make the collision-checking-rectangle of the player object slightly smaller than the actual sprite; that makes the life easier for your players.
First of all, you should always have your objects in arrays. This includes things like enemies, bullets and other such things. That way your game can create and destroy them at will.
You seem to be talking about the actual frequency of the collision checks, and not the collision check method. To that my advice would be to only run collision checks on a finite number of the objects. Try using a grid, and only checking for collisions with objects in the same grid block as the player.
Another thing that helps is to have plenty of "short cuts" inside the method itself. These are things that can be checked quickly and easily before any complex math is done. For example, you could check the distances between the two objects. If the objects are farther away than their farthest corner, you don't have to check for a collision.
There are plenty of these methods that you can utilize in your own unique combination.

GLGE API setRot/setRotX doesn't work

I'm trying to make a little scene for viewing 3D models.
I modified the GLGE Collada example to add a .dae model from code.
http://goleztrol.nl/SO/GLGE/01/
What I've got
So far it works. The camera is rotated using an animation.
Using the buttons 'Add' and 'Remove' the model is added and removed from the scene, using the following code (Don't mind 'duck'. It was a duck in the original example.)
var duck = null;
function addDuck()
{
if (duck) return;
duck = new GLGE.Collada();
doc.getElement("mainscene").addCollada(duck);
duck.setId("duck");
duck.setDocument("amyrose.dae");
duck.setLocY(-15);
duck.setRotX(1);
duck.setScale(2);
}
function removeDuck()
{
if (!duck) return;
doc.getElement("mainscene").removeChild(duck);
duck = null;
}
Problem
Now the model is lying down, while it should stand up. The various methods of the element seem to work. The location is set, and the scale is set, but the call to setRotX seems to be ignored. I tried various others methods from the api, but setRotY, setRot, setQuatX and setDRotX all seem to fail. I don't get any errors (well not about this method). I tried values of 1.57 (which should be about 90 degrees), but other values as well, ranging from 1 to 180.
I can't find out what I'm doing wrong. Of course I could rotate the model itself in Blender, but I'd like to do it using the GLGE API.
Update
When I load the demo-model, seymourplane_triangulate.dae, the rotation works. Apparently my model differs in that it cannot be rotated. I just don't understand why. I figured it may be because the model is built of various separate meshes, but I don't understand why scaling and moving does work.
Does anyone know what's wrong with this model, and what I could do to fix it (maybe using Blender)?
Setting an initial rotation in the XML file that contains the scene does work. Setting rotation on another element (like the whole scene) works as well.
You need to rotate it after it has been loaded.
You can do this in the callback to setDocument
duck.setDocument("amyrose.dae", null, function() {
duck.setLocY(-15);
duck.setScale(2);
duck.setRotX(0);
duck.setRotY(0);
duck.setRotZ(3);
});

Categories