I got an object (loaded with the loader, stl), where I'm trying to create a 'snapping' effect when moving it.
I create a THREE.Box3 from the object to do some detection stuff, but I noticed that my Box3 doesn't match my object's location object.location.
I'm sure I'm messing up worldspace, local space etc etc, so can anyone explain me how I could solve this and what is what?
Code:
var box = new THREE.Box3().setFromObject(activeElement);/
$("#debug").html(
"<p>location: <span>" + activeElement.position.x + " - " + activeElement.position.z + "</span></p>" +
"<p>box - min: <span>" + box.min.x + " - " + box.min.z + "</span></p>" +
"<p>box - max: <span>" + box.max.x + " - " + box.max.z + "</span></p>" +
"<p>sceneScale: <span>" + sceneScale);
So location and box-min don't fit, where they should fit.
box3 min and max are point vectors in 3D space, from the lower left behind to the upper right in front of the bounding box.
See this simple example values with a BoxGeometry and the size of (10,10,10):
mesh.position { x: 0, y: 5, z: 0 }
box.min { x: -5, y: 0, z: -5 }
box.max { x: 5, y: 10, z: 5 }
http://jsfiddle.net/L0rdzbej/12/
Update: as figured out in Chat, to place an object next to another ones bounding box use this formula (for snapping on one side of the x-axis):
newPosition.x = otherBox.min.x - ( (activeElement.max.x - activeElement.min.x ) / 2 )
Related
The problem is follow:
when the object has a positive angle and if negative angle is clicked - it follows logic and makes a counterclockwise rotation instead of clockwise rotation like it requires and vice versa. It doesn`t look like rotation of a unit in RTS games. How to fix it?
`
var object = document.createElement("div");
object.style.backgroundColor = "red";
object.style.width = "50px";
object.style.height = "50px";
object.style.position = "absolute";
object.style.transition = "transform 3s";
document.body.appendChild(object);
function action(event){
mousePosition = {
x : event.clientX - (object.offsetWidth/2),
y : event.clientY - (object.offsetHeight/2)
};
let unitBoundingRect = object.getBoundingClientRect();
let unitCenter = {
x: unitBoundingRect.left + unitBoundingRect.width/2,
y: unitBoundingRect.top + unitBoundingRect.height/2
}
let angle = Math.atan2(event.pageX - unitCenter.x, - (event.pageY - unitCenter.y))*(180 / Math.PI);
object.style.transform = "translate(" + mousePosition.x + "px," + mousePosition.y + "px) rotate(" + angle + "deg)";
object.innerText = Math.floor(angle);
}
window.addEventListener("click",action,false);
`
Here is the problem. We have two points (spheres) in xyz, with this info:
1- x,y,z => The center of the object is currently located at
2- r => The collision radius of the object
3- Vx, Vy, Vz => object is traveling along the vector. If that vector is (0,0,0), the object is stationary.
Note: The radii and positions are in meters and velocities are measured in meters per second.
Question: For each test, output a single line containing the time (in seconds) since the start of the test at which the two objects will first collide. If they never collide, print No collision instead.
I want to know about the formula of calculation this time. Any idea would be appreciated.
Examples:
1-
xyz(1): -7 5 0
v(1): -1 0 3
r(1): 3
xyz(2): 10 7 -6
v(2): -2 0 4
r(2): 6
t: 8.628 // this is the answer
2-
xyz(1): 10 3 -10
v(1): -9 3 -8
r(1): 5
xyz(2): 2 0 0
v(2): 6
r(2): -4 3 -10
t: 0.492 // this is the answer
To simplify problem, let us use Halileo's principle. Consider the first object as base point, so the second objects moves relative to it.
Put the first object position in coordinate origin.
Subtract the first object initial coordinates from the second one coordinates, do the same for velocity components
x2_0 = x2_0 - x1_0 (same for y,z)
Vx2 = Vx2 - Vx1 (same for y,z)
Now we have second center coordinates against time
x = x2_0 + Vx2 * t
y = y2_0 + Vy2 * t
z = z2_0 + Vz2 * t
and squared distance to origin:
dd = x*x + y*y + z*z =
(x2_0 + Vx2 * t)^2 + ... =
x2_0^2 + 2*x2_0*Vx2*t + Vx2^2*t^2 + ...
and we need to calculate when dd becomes equal to squared radius sum (r1+r2)^2
t^2 * (Vx2^2+Vy2^2+Vz2^2) + t*(2*x2_0*Vx2+2*y2_0*Vy2+2*z2_0*Vz2) +
x2_0^2 + y2_0^2 + y2_0^2 - (r1+r2)^2 = 0
Solve this quadratic equation for t, get 0,1 or 2 solutions.
Case of 0 solutions - no collision
Case of 1 solution with positive t - moment of touching
Case of two solutions - get smaller positive t for the moment of collision.
Negative values of t mean collision "in the past", before the start of the test
Quick test in Python (ideone)
from math import sqrt, isclose
def collisiontime(x1,y1,z1,vx1,vy1,vz1,r1, x2,y2,z2,vx2,vy2,vz2,r2):
x2 -= x1
y2 -= y1
z2 -= z1
vx2 -= vx1
vy2 -= vy1
vz2 -= vz1
a = vx2**2 + vy2**2 + vz2**2
b = 2*x2*vx2 + 2*y2*vy2 + 2*z2*vz2
c = x2**2 + y2**2 + z2**2 - (r1+r2)**2
D = b**2-4*a*c
if D < 0:
return None
if isclose(D, 0):
return -b/2/a
return (-b - sqrt(D)) / 2 /a, (-b + sqrt(D)) / 2 /a
print(collisiontime(0, 0, 0, 2, 0, 0, 2, 25, 0, 0, -3, 0, 0, 3)) # 1=> <=2
print(collisiontime(0, 0, 0, 2, 0, 0, 2, 25, 5, 0, 1, 0, 0, 3)) # 1==> 2=> chase with touching
print(collisiontime(-7, 5, 0,-1, 0, 3, 3, 10, 7, -6, -2, 0, 4, 6))
print(collisiontime(10, 3, -10,-9, 3, -8,5, 2, 0, 0, -4, 3, -10, 6))
(4.0, 6.0)
25.0
(8.627718676730986, 14.372281323269014)
(0.4917797757201004, 3.646151258762658)
I am using SVG.js and jquery to develop a simple yacht racing SVG animation to simulate a yacht race. I can easily animate an image [yacht icon] along the path. But I also want the yacht to rotate or the yacht heading change as the yacht travels up the path/route. I have tried a view things but cannot get it working. please help!
i am using this code..
function move_yacht_new(route,yacht,score){
var route1 = draw.path('M 535.07931,510.0164 C 594.9314,509.34072 667.14382,469.54596 691.80372,382.84271');
route1.fill('none');
var length = route1.length();
var y_pos = score;
var sailAngle = 90;
var currentRotation;
route1.hide();
var text = draw.text(function(add) {
add.tspan('We go ')
add.tspan('up').fill('#f09').dy(-40)
add.tspan(', then we go down, then up again').dy(40)
})
var image = draw.image('../globals/game/images/' + yacht + '-yacht.png',20, 20).id('yacht_' + yacht);
var scorePerc = (length/100) * (score);
//vdiscountPerc = calcPerc.toFixed();
var text = draw.text(yacht + ' (' + Math.round(score) + ')');
image.animate(5000, '<>').during(function(pos, morph, eased){
var p = route1.pointAt(eased * scorePerc);
image.move(p.x, p.y);
text.move(p.x, p.y).font({ fill: '#fff', size: 5, family: 'Helvetica', leading: '1.5em' });
var coord = image.bbox();
var center = coord.x + (coord.width/2) + ' '+ coord.y + (coord.height/2);
console.log('center ' + center);
var x_coord = image.attr('x');
var y_coord = image.attr('y');
//console.log(x_coord + ',' + y_coord);
image.rotate(-45, coord.x + (coord.width/2), coord.y + (coord.height/2));
var angle = Math.atan2(p.y, p.x) * 180 / Math.PI;//angle for tangent
//Shifting center to center of rocket
var centerX = p.x - 24,
centerY = p.y - 12;
console.log('angle > ' + angle);
//}).loop(true, true)
})
}
Blockquote
But this rotates the icons away from the path in a wrong direction.
I managed to resolve this using animation.js script.
Add the yacht icon into a group, translate the group along the path and rotate the yacht icon in the group around the group origin:
var g = draw.group()
var yacht = g.image(yachtUrl, width, height).center(0,0)
// in animate function:
g.transform(x: x, y: y)
yacht.transform(rotation: degrees, cx: 0, cy: 0)
Is there a way to create fading paths in d3.js, similar to the wind lines in the famous earth wind visualization:
http://earth.nullschool.net/
In principle, it seems like I could create a path with a lot of waypoints and transition each of the end segments toward transparency, but that seems hacky. Any better ideas?
To follow up on the example offered, here is a block on a reduced version. It is based on canvass as mentioned. The block illustrates the technique that I mentioned in my comments where the rendering engine is aggressively challenged which gives the blur effect for free. Click on the normal button to change to synchronous redraws and you can see that the blurring effect dissapears. This is achieved in the following code...
function run() {
paused = false;
then = Date.now();
now = then;
particles.forEach(function(p) {
p.t = now + (Math.random() - 1) * duration;
});
d3.timer(function(elapsed) {
var i = -1, n = particles.length;
var f = format(" >8.1f"), f3 = format(" >8.4f");
var normal = modeButton.text() == "normal", t;
if(normal) {
// clear the shadow context and copy the current context to it
offscreenContext.clearRect(0, 0, width, height);
offscreenContext.drawImage(canvas, 0, 0, width, height)
//clear the current context and try to jam the previous version
//back on top of the drawing activities
//lovely chaos ensues
context.clearRect(0, 0, width, height);
context.drawImage(offscreenCanvas, 0, 0, width, height);
}
else {
//allow the
context.clearRect(0, 0, width, height);
context.drawImage(offscreenCanvas, 0, 0, width, height);
offscreenContext.clearRect(0, 0, width, height);
}
now = elapsed + then;
//iterate the transition for each county
while(++i < n) {
var p = particles[i], t = (now - p.t) / duration;
if(t > 1) {
p.t += duration * Math.floor(t);
p.y = p.d.centroid[1] + (true ? (Math.random() - .5) * 2 : 0);
}
else if(t > 0) {
if(!normal){
offscreenContext.fillStyle = "rgba(" + p.r + "," + p.g + "," + p.b + "," + mirror(1 - t) + ")";
offscreenContext.fillRect(p.x + (t - .5) * p.v * 2 - .75, p.y - .75, 2.5, 2.5);
} else {
context.fillStyle = "rgba(" + p.r + "," + p.g + "," + p.b + "," + mirror(1 - t) + ")";
context.fillRect(p.x + (t - .5) * p.v * 2 - .75, p.y - .75, 1.5, 1.5);
}
}
}
return paused;
}, 0, now);
}
});
Here's a similar effect implemented in d3.js, though the code is compressed. You might find a way to reverse engineer it or find an uncompressed source.
It seems to me like each arcs is drawn only once it's the color that has a transition applied with a gradient that changes over time, and then is removed. I can't quite tell if all arcs share the same gradient and just start from different places, and appear at different times. That might be a great shortcut.
http://www.nytimes.com/interactive/2012/11/11/sunday-review/counties-moving.html
There's a presentation how this came to be, so perhaps they've talked about the tech elsewhere?
http://www.slideshare.net/openjournalism/amanda-cox-visualizing-data-at-the-new-york-times
(Quick note, I realize this isn't actually an answer, just needed more space than the comments section allows)
I'm probably doing something boneheaded here but I'm having difficulties getting alpha values to cooperate in Canvas. I'm trying to sample an opaque color from a spot on the canvas, make it more transparent, and lay it down in another spot -- but the alpha part doesn't seem to be working. Stripped down it goes sort of like this (condensed from functions strewn across the script):
p = ground.ctx.getImageData(loc.x, loc.y, 1, 1).data;
col = {R: p[0], G: p[1], B: p[2], a: p[3]};
col.a = col.a - 0.1;
ground.ctx.fillStyle = 'rgba(' + col.R + ', ' + col.G + ', ' + col.B + ', ' + col.a + ')';
ground.ctx.fillRect(nuLoc.x, nuLoc.y, sqrSize, sqrSize);
It all runs, but when I test the value of fillStyle I get just a standard RGB "#fa674c" or whatever -- no mention of any alpha -- and when I getImageData() from the newly drawn Rect the value is fully opaque again.
Another thing I haven't been able to figure out either empirically or by reading every tutorial (and the spec) is whether alpha wants to be 0-1.0 or 0-255. Most sources talk about 0-1.0 -- but getImageData() returns 0-255... and I can't make it work either way.
Use context.globalAlpha instead of using rgba fill:
p = ground.ctx.getImageData(loc.x, loc.y, 1, 1).data;
col = {R: p[0], G: p[1], B: p[2], a: p[3]};
// note: globalAlpha uses a scale of 0-1
// and getImageData uses a scale of 0-255
ground.ctx.globalAlpha = a/255-.1;
ground.ctx.fillStyle = 'rgb(' + col.R + ', ' + col.G + ', ' + col.B + ')';
ground.ctx.fillRect(nuLoc.x, nuLoc.y, sqrSize, sqrSize);
// reset globalAlpha when you're done
ground.ctx.globalAlpha = 1;