Three.js starting and stopping a simple mesh - javascript

I am still new to Three.js and WebGL but I want to get better at it. Could you please check my code having found a solution to a fairly simple problem that I set for myself.
SIMPLE PROBLEM (that took too long to solve):
How can I animate a simple 400 x 400 PLANE MESH from y position 500 (below browser window) to x,y,z position 0 (centre of the browser window) - WITHOUT using Tween.js? I know Tween.js for Three.js is very efficient for simple movements but I wanted to find a solution that involves learning. Use Tween.js and I don't learn anything. And yes, I did hours of research looking at various solutions on StackOverflow and on Mr Doob's code repository on GitHub. After very extensive searching, I couldn't find a solution that gave me exactly what I wanted, namley: A simple vertical upward animation STARTING out of frame AND STOPPING in the centre of the browser window.
MY SOLUTION:
`function animate() {
var newPos = plane.position.y;
plane.translateY( 4 );
function stopHere () {
if (newPos >= 0)
{
plane.position.set( 0, 0, 0);
var stopPlane = plane.position.y = 0;
}
}
requestAnimationFrame(stopHere);
}
function render() {
renderer.render(scene, camera);
animate();
}`
I've posted just the two functions that do all the work. Does anyone see bad practice there? My logic is that
requestAnimationFrame
cannot be in the render(); function, as it needs to be within the scope of the nested function ('stopHere') within
`animate();`
I ran into difficulty approaching it from this direction:
`objMesh.geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 1, 0.1, 0.1 ) ); `
After wrestling with something simple for over a week, I just know it works. To my understanding, I have used a method of the applyMatrix sub-class and made it work. I'm asking for comments because I want to learn Three.js, not bad habits. Please, does anyone see bad practice or bad coding? Many thanks.
ksqInFlight

I am a senior citizen, so my approach is, in your requestAnimationFrame loop:
function fnloop() {
var dy = Math.min(Math.abs(plane.position.y), .01); // max movement
if (Math.abs(dy) >= .000001) {
if (plane.position.y > 0) dy = -dy; // move down if above
plane.position.y += dy; // move up or down
if (Math.abs(plane.position.y) < .000001) alert("Done!");
}
renderer.render(scene, camera);
requestAnimationFrame(fnloop);
}

Related

How do you get a THREE.Line to render in the right order?

I'm working on a model solar system and I am using THREE.Line to make my orbits. They look fine until you go in front of a planet and you realize that they are all being rendered behind the Meshes. I've tried playing around with render order and depthwrite but they just make it so that the line is either entirely in front of or entirely behind the planet. I feel like this should be an extremely easy thing to do.
The effect, if you'd even consider it an effect is like this:
what i'm looking for, you can see one orbit that fully wraps around that planet.
this is what my problem looks like:[what i have][2].
Here is the function that makes my orbits:
function MakeOrbit_2(base, color) {
function semiminor(a, e) {
return a * Math.sqrt(1 - (e * e));
}
var curve = new THREE.EllipseCurve(
foci(1000 * base[9], semiminor(1000 * base[9], base[0])), 0, // where the middle is
1000 * base[9], semiminor(1000 * base[9], base[0]), // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
var material = color;
var geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(points))
var orbit = new THREE.Line(geometry, material);
orbit.rotateX(- Math.PI / 2);
orbit.rotateZ(DegToRad(base[3]));//ascn
orbit.rotateX(DegToRad(base[2]));//inc
orbit.rotateZ(Math.PI + DegToRad(base[4]));//aop
scene.add(orbit);
return orbit;
}
I have renderer.sortObjects = false; so my transparent atmospheres and clouds render properly.
It is also worth noting that my less opaque lines behave differently than the fully opaque ones.
Update: turns out this weird effect was due to rounding errors, the scale was on billions of units and the difference in position were too minuscule to bother the z-buffer.
I found a working example by Sander Blue along with his GitHub source code. I was unaware of 3D Javascript until I saw this post, amazing! Also your name... my mom's family name is Logan and my dad's is Brotherston... how about that? I don't have a direct answer to your question but I hope that these links help. It appears to be a working example of just what you were asking about... showing orbits in front of a planet as you rotate the view.

Canvas rendering dependent on unrelated elements?

I'm trying to make an environement to train a neural network.
At first I just made a 3d canvas and rendered that which worked fine (#canvas in the code), then I converted that to an image.
Later I found out that I needed to convert the canvas to 2d to be able to get the image data I need to input into the AI (according to the advice I got here.
I also discovered a bug which made me call animate() twice.
The weird thing is that if I now try to remove either the image-rendering or the extra call to animate(), the 2d canvas wont render when the camera is moved in Chrome, while it renders irregularly in IE. Any idea how I can fix this?
I have cut down the code to the essentials in this
fiddle, the animation loop is below:
function animate(){
requestAnimationFrame( animate );
movement();
hudUpdate();
//fps-calculation
newTime = Date.now();
sumTime += (newTime - oldTime);
if(framesElapsed === 60){
document.getElementById("fps").innerHTML=
(Math.floor(600000/sumTime))/10;
framesElapsed = 0;
sumTime = 0;
} else {
framesElapsed+=1;
}
oldTime = newTime;
//Converts the canvas to an image and then draws it on a 2d surface.
// CHECKT THIS! Has to be run before renderer.renderer, but will be blank
if movvement occurs and the segment below is left out.
var image = convertCanvasToImage(drawingSurface);
var AIInputImage = convertImageToCanvas(image);
renderer.render(scene, camera);
// CHECK THIS! the above conversion stops working while moving unless the
the line below is present, no idea why..
$("#interim-img").attr("src",drawingSurface.toDataURL("image/png"));
};
animate();
animate();
Edit: updated fiddlelink.

Animating canvas' .stroke() without external libraries

I know it's been asked quite a lot (I did google it), but how can I animate .stroke() command on canvas? I found some examples, but they all rely on external overpowered (for my purposes) libraries or require use of pre-generated SVG files.
I have this page here (I know it sucks, but I am learning the curves with it among other things). What I need is to make the lines coming of the bottom "button" to "grow" or have an effect at least similar to what other buttons provide with circle. For circles I used jquery's knob library, but for lines... It feels like this can be done with transformation or something, but I can't put my finger on it. Any advice?
There are a couple ways to do this, but the easiest (and native) method doesn't require much code. Here is a WORKING FIDDLE of a canvas stroke() animation. The accompanying JavaScript is below. This is a very simple example, but it should give you the right idea.
var canvasObj = function() {
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
x = 0,
y = 0,
animate = function() {
ctx.beginPath();
ctx.moveTo( 0, 0 );
ctx.lineTo( x,y );
ctx.stroke();
x += 5;
y += 2.5;
setTimeout( animate, 200 );
};
return {
'animate': animate
};
};
Explanation: The thing that makes this work is the closure that is created by the internal function animate within the canvasObj function. The variables x and y are available at the parent function level, and can be manipulated by the animate function. animate is calling itself by using setTimeout which creates the animation effect. And that's really it. Hope this helps you get on your way.

Dynamic bones animation in Three.js

Is it possible to create a dynamic animation by applying transformations to the bones of a 3D model using three.js? I tried moving and rotating the bones of a SkinnedMesh, but the mesh was not updated.
loader = new THREE.JSONLoader();
loader.load('/JS-Projects/Virtual-Jonah/Modelos/initialPose.js',function jsonReady( geometry )
{
mesh = new THREE.SkinnedMesh( geometry, new THREE.MeshNormalMaterial({skinning : true}) );
mesh.scale.set( 10, 10, 10 );
mesh.position.z = mesh.position.y = mesh.position.x = 0;
mesh.geometry.dynamic = true;
scene.add( mesh );
var index = 0;
for (var i = 0; i < mesh.bones.length; i++)
{
if (mesh.bones[i].name == "forearm_R")
{
index = i;
break;
}
}
setInterval (function ()
{
mesh.bones[index].useQuaternion = false;
mesh.bones[index].position.z += 10;
mesh.bones[index].matrixAutoUpdate = true;
mesh.bones[index].matrixWorldNeedsUpdate = true;
mesh.geometry.verticesNeedUpdate = true;
mesh.geometry.normalsNeedUpdate = true;
renderer.render(scene, camera);
}, 33);
renderer.render(scene, camera);
});
The model I am using was created with makeHuman (nightly build), exported to Collada, imported in Blender and exported to the three.js JSON model. The link to the model is the following:
https://www.dropbox.com/sh/x1606vnaoghes1y/gG_BcZcEKd/initial
Thank you!
Yes, you can!
You need to set mesh.skeleton.bones[i], both mesh.skeleton.bones[i].rotation and mesh.skeleton.bones[i].position. Rotation is of type Euler. Position is of type Vector3. I have actually tested this using my code from here https://github.com/lucasdealmeidasm/three-mm3d (that includes a working skinned mesh with bone-attachable objects) and one can indeed do that.
Note that Inateno's answer is very wrong, there are many instances where this is necessary.
For example, in a FPS, one uses both dynamic and non-dynamic animation.
When a character runs and holds a gun, the direction he points the gun at is dynamically set (one could use mesh.skeleton.bones[i].rotation where "i" is the index for bone assigned to the arm for that) while the rest of the animation, including the walking, is made in the editor and loaded. One can, in three.js, use "THREE.AnimationHandler.update(delta);" and then change single bones' position and rotation in code to solve those issues.
I know you can export a bone driven animation from Blender in JSON format, for use in THREE.js, there are a few tutorials of that around the web. I hope this helps. Good Luck.
If I understund you want to create animations yourself inside the code ?
You are note supposed to do this, in Unity you have a simple animation editor, you never manipulate bones directly in code.
It's long, boring, unperforming. To animate a model use animation directly.
Here's a result of animation with some bones manipulation but there is an animation over.
http://threejs.org/examples/webgl_animation_skinning_morph.html
Here is a tutorial about making simple animation if you need http://blog.romanliutikov.com/post/60461559240/rigging-and-skeletal-animation-in-three-js
And here a related post about animations problems just in case
Blender exports a three.js animation - bones rotate strangely
Hope this will help you :)

Question about the javascript-canvas object (save, transform, restore)

I've been playing around with canvas a lot lately. Now I am trying to build a little UI-library, here is a demo to a simple list (Note: Use your arrow keys, Chrome/Firefox only)
As you can tell, the performance is kinda bad - this is because I delete and redraw every item on every frame:
this.drawItems = function(){
this.clear();
if(this.current_scroll_pos != this.scroll_pos){
setTimeout(function(me) { me.anim(); }, 20, this);
}
for (var i in this.list_items){
var pos = this.current_scroll_pos + i*35;
if(pos > -35 && pos < this.height){
if(i == this.selected){
this.ctx.fillStyle = '#000';
this.ctx.fillText (this.list_items[i].title, 5, pos);
this.ctx.fillStyle = '#999';
} else {
this.ctx.fillText (this.list_items[i].title, 5, pos);
}
}
}
}
I know there must be better ways to do this, like via save() and transform() but I can't wrap my head around the whole idea - I can only save the whole canvas, transform it a bit and restore the whole canvas. The information and real-life examples on this specific topic are also pretty rare, maybe someone here can push me in the right direction.
One thing you could try to speed up drawing is:
Create another canvas element (c2)
Render your text to c2
Draw c2 in the initial canvas with the transform you want, simply using drawImage
drawImage takes a canvas as well as image elements.
Ok, I think I got it. HTML5 canvas uses a technique called "immediate mode" for drawing, this means that the screen is meant to be constantly redrawn. What sounds odd (and slow) first is actually a big advantage for stuff like GPU-acceleration, also it is a pretty common technique found in opengl or sdl. A bit more information here:
http://www.8bitrocket.com/2010/5/15/HTML-5-Canvas-Creating-Gaudy-Text-Animations-Just-Like-Flash-sort-of/
So the redrawing of every label in every frame is totally OK, I guess.

Categories