Animation is too fast in Three.js - animation

I'm loading my model and skeletal animation using the ColladaLoader into Three.js and it appears to be doing the right movements as far as I can tell, but the animation is ridiculously fast for some reason. How do you control the speed of the animation?

var animation = THREE.Animation( mesh, animationData );
animation.timeScale = 1/5 ; // add this
the default timeScale is 1, reduce it to lower your animation

Related

Three.js - strange shading behaviour

Where does the vertical shadow on the left cube come from?
https://jsfiddle.net/yz0sfr35/
//I'm using:
renderer.shadowMap.type = THREE.BasicShadowMap;
What you are seeing is pixelation in your shadows due to the fact that your shadow camera frustum is orders-of-magnitude larger than your scene.
One solution in your case is to reduce the angle of your spotlight:
light.angle = Math.PI / 180;
Keep your shadow frustums tight around your scene for quality shadows.
https://jsfiddle.net/yz0sfr35/2/
three.js r.87

THREE.js: Looking for an alternative to MeshFaceMaterial

According to various posts at the three.js github, MeshFaceMaterial will be deprecated eventually.
I currently use this for my terrain. Granted it's not the best way to do it. Actually its pretty crappy. For one I cannot use BufferGeometry which is not good considering I generally have 2 layers of 128x128 (segmented) planes for terrain. Very high memory usage.
I've adapted all my code to allow for the terrain to be BufferGeometry except two things don't work. MeshFaceMaterial and BufferGeometry.merge(). The merge doesn't work on indexed geometry which to me is weird considering THREE creates this geometry, yet it can merge non-indexed geometry from blender. It cannot merge geometry it creates itself but can merge geometry from external sources... Oh well that's another post there, back to MeshFaceMaterial.
I currently use a 128x128 "MaterialMap". Each pixel represents a materialIndex for each face of the plane. This has two serious drawbacks. Squared up sections of terrain (no curves) and harsh distinctions on the borders of textures.
My question is: How can I generate this terrain with multiple textures without using MeshFaceMaterial. The highest res texture I have is 2048x2048 and zone size can easily be 10000x10000 making repeat necessary (right?).
Ultimately my goal is to use BufferGeometry and get rid of MeshFaceMaterial.
MaterialMap example:
Terrain Example (terribly cropped sorry {work pc}):
You helped me out a while back via email with advice on culling meshes so I would like to return the favor (with my humble strategy) :)
If you want to use THREE.PlaneBufferGeometry (which, as you know, is where all geometry in THREE.js is soon headed), then my advice would be to layer different PlaneBufferGeometries right on top of each other. For instance in the above example picture, you could have
var stoneFloorGeometry = new THREE.PlaneBufferGeometry(arenaWidth, arenaHeight, 1, 1);
var stoneFloorMaterial = new THREE.MeshBasicMaterial({
depthWrite: false, // This is always underneath every other object
map: stoneFloorTexture
});
var stoneFloor = new THREE.Mesh(stoneFloorGeometry, stoneFloorMaterial);
stoneFloor.rotation.x = Math.PI / -2; // rotate to be flat in the X-Z plane
stoneFloor.position.set(0, 0, 0);
scene.add(stoneFloor);
// now add the grass plane right on top of that with its own texture and shape
var grassGeometry = new THREE.PlaneBufferGeometry(lawnWidth, lawnHeight, 1, 1);
var grassMaterial = new THREE.MeshBasicMaterial({
depthWrite: false, // this is rendered right on top of the stone floor
map: grassTexture
});
var grass = new THREE.Mesh(grassGeometry, grassMaterial);
grass.rotation.x = Math.PI / -2;
grass.position.set(0, 0, 0);
scene.add(grass);
// finally add the stone path walkway on top of the grass, leading to the castle
var walkwayGeometry = new THREE.PlaneBufferGeometry(walkwayWidth, walkwayHeight, 1, 1);
var walkwayMaterial = new THREE.MeshBasicMaterial({
depthWrite: false, // this is rendered right on top of the grass
map: stoneFloorTexture // uses same texture as large stoneFloor before
});
var walkway = new THREE.Mesh(walkwayGeometry, walkwayMaterial);
walkway.rotation.x = Math.PI / -2;
walkway.position.set(0, 0, 0);
scene.add(walkway);
As long as you layer the level from bottom to top and disable depthWrite, all the various textures will correctly show up on top of each other, and none will Z-fight. So, stoneFloor is added to the scene first, followed by grass, followed by walkway.
And since depthTest is still active, your moving game characters will render on top of all these various textures. Initially, it also looked like it worked with just disabling 'depthTest', but the textures ended up rendering over ('above') the characters/models which is incorrect.
Eventually when THREE.js moves ShapeGeometry over to BufferGeometry, it would be nice to define an arbitrary polygonal shape (like an octagon or something) and then texture map that and lay down shapes on top of each other for the game level in a similar manner, thus avoiding the 'square' problem you mentioned.
As for this current solution, on the modern CPU/GPU I don't think you will see much performance cost in creating 3 PlaneBufferGeometries instead of 1 large one with multiple faces/indexes. This way you have the advantages of using THREE's BufferGeometry while still having everything 'looking' like it is all texture-mapped to one large plane.
Hope this helps!
-Erich (erichlof on GitHub)

Three.js pixel perfect at z=0 plane

Is there any way to configure the camera in Three.js so that when a 2d object (line, plane, image) is rendered at z=0, it doesn't bleed (from perspective) into other pixels.
Ex:
var plane = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), material);
plane.position.x = 4;
plane.position.y = 3;
scene.add(plane);
...
// Get canvas pixel information
context.readPixels(....);
If you example the data from readPixels, I always find that the pixel is rendering into its surrounding pixels (ex: 3,3,0 may contain some color information), but would like it to be pixel perfect if the element that is draw is on the z=0 plane.
You probably want to use THREE.OrthographicCamera for the 2d stuff instead of THREE.PerspectiveCamera. That way they are not affected by perspective projection.
Which pixels get rendered depends on where your camera is. If your camera for example t z=1 then a lot of pixels will get rendered. If you move your camera to z=1000 then you see, due to perspective, maybe only 1 pixel will get rendered from your geometry.

Automatically keep texture's ratio and texture's size when repeating

I'm using three.js to build a house, i have walls and textures for walls.
Walls are basically CubeGeometry.
I took a unique scale : 1cm = 1px
textures could be bricks or any other construction materials, but textures files are always 512x512 with details in it. for example : One brick in the texture file will be 10px per 4px.
I need to keep this ratio to keep the reality of the scene.
var texture = THREE.ImageUtils.loadTexture("images/wall.jpg");
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat = new THREE.Vector2(0.2 , 0.2);
var wall = new THREE.Mesh(new THREE.CubeGeometry(100, 100, 10), new THREE.MeshBasicMaterial({ map: texture }));
that's works quite well because the case is simple ;), it is also very simple to made a ratio for every walls (which can have any sort of sizes)
But in fact i have plenty of other geometries (procedurally generated and so on), is there by any chance a property like : "THREE.KeepMyTextureSizeAndRepeat" wrapping ? Or will i need to make ratios for each of my custom geometries ?
If you have any advice on this use case, i will be greatfull :)
Many thanks
EDIT : the final goal is to do something like "patterns" in 2D canvas
var pattern = context.createPattern(imageObj, repeatOption);
context.fillStyle = pattern;
context.fill();
when you do something like that, on a rect for example the pattern will be repeated keeping the aspect ratio (e.g http://www.html5canvastutorials.com/tutorials/html5-canvas-patterns-tutorial/)
you'll have to calculate every ratio by yourself because a texture doesn't know anything about the pixels. It only knows about the uvs.

Rotating a single image (but not the others) on an html5 canvas?

I have a sprite I'm animating on an html canvas using normal sprite sheet blitting. On certain key events I'd like to change the direction of the sprite (ie, flip it, or rotate it 180 degrees) without changing anything (the other sprites) on the canvas.
Does anyone know how to do this?
So I was having this issue with my game; I had cells for up, down, and left animations, but no right cells. So I needed to flip the left cells to draw the right cells.
For each sprite I keep track of it's current top and left in the canvas, as well as each cell's top and left in the sprite sheet.
I've seen previous answers showing a simple horizontal flip as just translating the origin and flipping (inverse scale) of the axes, BUT this does not take into account that with sprites, flipping the origin will mess up the sprite's registration point (its top and left on the canvas).
This issue manifested in the sprite being mirrored correctly, but it's position being off by the width of the sprite. I solved it by taking into account the width of the sprite. Notice how I'm using CanvasRenderingContext2D.prototype.drawImage with 9 arguments since I'm slicing a sprite out of a sprite sheet:
// check if we need to flip image (special case for right movement)
if(sprite.translated){
context.save();
context.translate(context.canvas.width, 0);
context.scale(-1, 1);
context.drawImage(sprite.sheet,
cell.left,
cell.top,
sprite.width,
sprite.height,
// secret sauce: change the destination's X registration point
context.canvas.width - sprite.left - sprite.width,
sprite.top,
sprite.width, sprite.height);
context.restore();
} else {
// Assumes cells are all the same width and height, set in sprite
context.drawImage(sprite.sheet, cell.left, cell.top, sprite.width,
sprite.height, sprite.left, sprite.top, sprite.width, sprite.height);
}
Note: I also could have done the math in the translate, since it's meant to simplify calculations elsewhere.
Simply redraw the sprite, with a rotate transformation. Transformations in HTML Canvas 2D Context
The canvas is just an off-screen buffer. It won't be cleared unless you tell it to, and nothing else will be changed unless you tell it to.
There's a bunch of different situations in which you may have to redraw the area of or around the sprite. Otherwise, you'll get a ghosting effect where part of the old sprite is still visible below the new drawing, or other drawings become obscured. Some reasons are:
Your sprite is partially transparent,
Your sprite is partially translucent,
Other drawings are made on top of your sprite,
Your sprite is non-rectangular,
You're doing flips that are not multiples of 90 degrees.
So that might be a bit more work, and there are several different approaches to doing that. You could simply redraw the entire scene, or just the specific objects at the location, perhaps using the clip method.
A completely different direction might be to use other HTML elements, img or div, with absolute positioning and CSS3 transformations. That's basically a bit of trickery to delegate the rendering of your scene to the browser.
While I appreciate Shtééf's answer, after a bit of research, I have found that rotating the canvas you are actually using to display doesn't seem to be ideal. The saving, rotating and restoring while trying to create complex animations (aka think Street Fighter 2 not astroids) causes the canvas to flicker in even Chrome.
I have found however a usable strategy. The idea here is that you actually create two canvases, one will be for your game and the other will be a backbuffer of sorts and it will be used to rotate or scale your sprites. You essentially transform the backbuffer canvas, draw the image in question, then transfer it to your main canvas and restore (or not) the backbuffer. In this manner, you only rotate the hidden canvas and only effect the sprite in question not the entire game board.
The code looks something like this (work in progress):
mainContext.clearRect(lastXpos, lastYpos, lastWidth, lastHeight);
backContext.clearRect(0, 0, lastWidth, lastHeight);
lastXpos = xpos;
lastYpos = ypos;
lastWidth = width;
lastHeight = height;
backContext.save();
//check the direction of the sprite
//turn the backContext to this direction
//SPRITE_INVERTED==-1
if (spriteXDirection == SPRITE_INVERTED || spriteYDirection == SPRITE_INVERTED)
{
var horScale = 0;
var verScale = 0;
if (spriteXDirection == SPRITE_INVERTED)
{
horScale = width;
}
if (spriteYDirection == SPRITE_INVERTED)
{
verScale = height;
}
backContext.translate(horScale, verScale);
backContext.scale(spriteXDirection, spriteYDirection);
}
//draw the sprite not we always use 0,0 for top/left
backContext.drawImage(animations[currentPlay].sheet,
animationX,
animationY,
width,
height, 0, 0, width, height);
//Get the image data from the back context
var image = backContext.getImageData(0, 0, width, height);
//flip the back context back to center - or not, I haven't decided how to optimize this yet.
backContext.restore();
//transfer the image to your main context
mainContext.putImageData(image, xpos, ypos);
This has saved me a lot of headaches in understanding how to translate my sprites without having everything on my gameboard move all over the place. It also seems to perform better then modifying the main context.
Why don't you use save() and restore
ctx.save(); // save current state
ctx.rotate(Math.PI); // rotate
ctx.drawImage(link,x,y,20,20); // draws a chain link or dagger
ctx.restore(); // restore original states (no rotation etc)
How to rotate one image in a canvas?

Resources