I've been playing around with using matrices to hold transforms for 2D elements in canvas. setTransform works pretty well for this, but I ran into an interesting issue where I get the Moire effect when I try to render a transformed cube at the coordinates (0, 0). Setting the coordinates to (0, 1) or (1, 0) fixes this. Also the problem seems to only be with fillRect, rendering text instead of the cube works just fine.
Example Pen: https://codepen.io/danman113/pen/mdEYdKx
I figured out a solution but I still don't fully understand why I was getting a Moire pattern. I would love if someone could explain that to me.
The solution was to reset the transform after setting it. I'm not sure why this works as I thought setTransform implicitly reset the transform after it was called.
c.setTransform(transform[0], transform[3], transform[1], transform[4], transform[6], transform[7])
c.fillRect(0, 0, 100, 100)
c.resetTransform()
Working example: https://codepen.io/danman113/pen/dyXEGQw
EDIT:
As Kaiido points out in his comment, the Moire effect happens because clearRect() is also transformed. Adding the resetTransform fixes this.
Related
I am using ammo.js to create a simple demo.
I have a 3d object in the world and I can make it move with the following code:
cubeObject.applyForce(new Vec3(10, 0, 0));
It will move along the x-axis and then stop gradually.
Now I want to make it to turn a little bit (imagine a car turning):
cubeObject.applyTorque(new Vec3(0, 1000, 0));
After calling this code, the cube (car) dose turn a certain degree (this is good as expected).
But the problem is, the car is still moving along the x-axis instead of moving towards the direction it is facing (after turning).
I do not know what I am missing here.
Any advice will be appreciated, thank :)
I am trying to create an online image editor using HTML5 and getting issue while perform image move. pixelization happens everytime when I try to move, zoom, drag, rotate. I think issue is clearRect function.
function clear() {
element.clearRect(0, 0, window.innerWidth, window.innerWidth);
}
Here is my Fiddle Project
You are playing with the matrix transformations of the canvas' context.
These also apply to the clearRect method.
You need either to calculate the current transformations and apply their negative value to the clearRect method, or to reset the transformation matrix.
One easy way to do so is by using the setTransform method and the default values for the transformation matrix : ctx.setTransform(1,0,0,1,0,0);
Updated fiddle, with a quick fix.
very interesting topic. Nice exercise, too. I picked your fiddle.
Here is the result:
https://jsfiddle.net/dh6y18yh/8/
var loopRunner = function() {
drawImage();
globalID = requestAnimationFrame(loopRunner);
};
Basically the main big difference is, that I decoupled ALL the parameters for the image positioning into variables. Then do the translate(x,y) in drawImage()
and let drawImage() be run in a window.requestAnimationFrame() loop.
This way in is rendered correctly at 60 fps.
The mouse dragging is now calculating the distance dragged, and set this value to the position values.
I want to be able to drag an object, but have it 'snap' to the surface of another.
I don't care if it only 'snaps' when I release the mouse, or if it updates live.
Ultimate goal: create a smooth shape in Blender, import it, and be able to snap drag to that shape. I know I can do this with procedurally generated surfaces with a bit of math, but I'm looking to use some non-procedurally generated surfaces.. or at least, the surfaces I'm wanting to use I haven't figured out how to generate procedurally yet.
I tried taking this example: http://stemkoski.github.io/Three.js/Mouse-Click.html and changing the 'click' effect to a 'drag' effect. Then I incorporated it with this example: http://mrdoob.github.io/three.js/examples/webgl_interactive_draggablecubes.html
The effect is working, in that I can drag any of the cubes across the sphere, and the face hilights.
Then I tried taking the dragged object, and snapping it to the face of the sphere using this flawed logic:
SELECTED.position.x = intersectsRay[ 0 ].face.normal.x;
SELECTED.position.y = intersectsRay[ 0 ].face.normal.y;
SELECTED.position.z = intersectsRay[ 0 ].face.normal.z;
The problem: the dragged objects always snap to the center of the sphere...
The reason being, (I think . . . ) is the face 'normal' is the center of the (sphere) in this case.
Does anyone know a way to find the x,y,z of the FACE (no matter what the shape), or any other way to implement this concept?
An easy solution would be to not use the local (and normalized) face normal, instead for example you could use the vertex index.
Something like:
intersectedOBJ.geometry.vertices[intersect.face.a]
This way, you would snap your dragged object to one of the face's vertices.
Also there is a face "centroid" that you can use or you could calculate the center of the face on your own.
I'm writing a game using HTML5/WinJS on Windows 8. I'm trying to produce the effect of a bullet or missile firing at something; however, I can't seem to get the object to go through another image in the background without trailing a border. My working theory is that the border I'm seeing is caused by using clearRect. Here's my code:
var moveBullet = function(missile) {
if (missile.Image == undefined || missile.Image == null) {
var image = new Image();
image.src = "/images/missileImg.png";
image.onload = function () {
canvasContext.clearRect(missile.PointX - (image.width / 2), missile.PointY, image.width, image.height);
missile.PointY += BULLET_SPEED;
canvasContext.drawImage(image, missile.PointX - (image.width / 2), missile.PointY);
};
} else {
canvasContext.clearRect(missile.PointX - (missile.Image.width / 2), missile.PointY, missile.Image.width, missile.Image.height);
missile.PointY += BULLET_SPEED;
canvasContext.drawImage(missile.Image, missile.PointX - (missile.Image.width / 2), missile.PointY);
}
}
Is there a way to achieve this effect without using clearRect, or a more efficient way of restoring the background as it moves past?
Make your clearRect area a few pixels larger than the missile image. Drawing on a canvas in general has some built-in anti-aliasing. This means that if you draw a line with one color, then draw the same line with the background color, you'll not remove the original line. Something similar might be happening here, in which case a few extra pixels should help.
That said, there's a caveat to be aware of here.
First, I assume the background is separate element from the canvas? It looks like it as you're not redrawing that part on the canvas itself.
The reason I ask is that making repeated calls to clearRect on the same canvas will eventually show performance problems. What happens is that every call to clearRect accumulates into a complex region within the canvas--essentially its transparency mask. So every time the canvas has to be rendered, which happens any time you change it, it has to process that transparent area. Gradually, as you leave more and more small clearRect trails across the canvas, this region will become more and more complex and performance will drop.
I did this experiment with the Blizzard demo on the IE Test Drive site once, where I wondered why the demo was clearing the entire canvas with every animation frame. So I tried just clearing the trail behind each snowflake (and made each one a little bigger as I suggest above, because I had trails). Seemed like the right thing to do, but the performance plummeted by several orders of magnitude. Asking around within the IE team, they confirmed the region behavior I describe.
So the best thing to do, actually, is to do a clearRect on the entire canvas with every frame, then redraw the missile and any other bits that you're animating. This may seem counter intuitive, but ends up working best and avoids all these glitches with pixel trails.
I'm trying to draw a grid on a <canvas> element with the ultimate goal of making a Go board.
For some reason the grid is looking stretched, with the lines being thicker than 1 pixel and the spacing being completely wrong. It doesn't even start in the (10,10) position..
It would be great if someone could take a look at tell me what I'm doing wrong.
http://jsfiddle.net/h2yJn/
I've found the problem. I was setting the dimensions of the <canvas> using CSS, when you actually have to set the width and height attributes. This was causing it to be stretched/skewed.
var canvas = $('<canvas/>').attr({width: cw, height: ch}).appendTo('body');
http://jsfiddle.net/h2yJn/66/
Please try it outside jsfiddle, maybe jsfiddle is applying some linear transformation.
Also please make sure that you add 0.5 everywhere to both x and y coordinates. Alternatively, you can apply translate(0.5, 0.5) to shift all coordinates by half a pixel.