Limit camera rotation on the Y axis - javascript

I am using JSModeler to display OBJ files. It internally uses THREE.JS and creates a PerspectiveCamera. What I need is to limit the movement of the camera on the Y axis so not to go underneath the object. I know how to do this with THREE.OrbitControls but this doesn't work with JSModeler. Is there a way to directly control the camera movement? Thanks.

jsmodeler creates its own set of controls which it stores in JSM.navigation object.
viewer = new JSM.ThreeViewer ();
camera_object = viewer.navigation.camera
The drawLoop function takes in values in this viewer.navigation.camera and renders them on the canvas. So, suppose if you change the values in the viewer.navigation.camera, and call drawCallback(), the changes would get rendered.
viewer.navigation.camera.eye.x = 1; // Any value you want
viewer.navigation.camera.eye.y = 1; // Any value you want
viewer.navigation.camera.eye.z = 1; // Any value you want
viewer.navigation.drawCallback();

Related

Add new elements based on position and rotation angle of main element

I'm building a game in vanilla javascript where you can spot fishes on a radar. What I'm trying to achieve is the following:
I want objects (fish) to show up randomly on the position of the dial (randomly on the width/height) while its spinning. I am able to get the angle of the dial, and the position, but I have no idea how to calculate the position of the new objects.
My current ugly solution involves creating a temporary div inside the dial, get the position, and use those for the new object, but it doesn't really work properly.
See this fiddle for what I have so far
function createNewFish() {
// Create new fishies
/*
const pos = document.getElementById('dial').getBoundingClientRect();
const degrees = getDialDegrees();
console.log(pos)
console.log(degrees)
// Calculate position for fish?
*/
For anyone attempting to do the same, I've managed to solve it using the following solution:
When you have a dial that spins, you can fill the dial with some equal divs (I used 9) like so:
function DialGenerator() {
for(let i=0;i<9;i++) {
const insideDial = document.createElement('div');
insideDial.classList.add('dial-inside')
insideDial.setAttribute('id', 'dial-inside-'+i)
document.getElementById('dial').appendChild(insideDial)
}
}
Then if you want to show elements on random positions on the dial (like my radar needs), you can just get a random div inside the dial using Math.random() and get the position of this div:
function getPosition() {
const n = getRandomNumber(1, 6);
// Get a random position on the dial for the fish to appear on
const dialPosition = document.getElementById('dial-inside-'+n).getBoundingClientRect();
return {'top':dialPosition.top, 'left':dialPosition.left}
}
This returns the position of the div on the dial, which you can use to place your elements on the radar.
Hope this helps someone!

Is there a Move towards function in three.js

I am new to three.js. I was wondering if there is a function like move towards from unity in it? A function that we can use to move our object from it's current position to some Vector3.
Thanks.
I actually managed to solve this.
Here it is for anyone else stuck on this.
But you have to make sure that the object is a child of a THREE.Group and you move the THREE.Group instead of the object because the function doesn't behave right if the object's rotation is changed.
var targetPosition = new THREE.Vector3(x,y,z);
var objectToMove;
var group = new THREE.Group();
group.add(objectToMove);
var targetNormalizedVector = new THREE.Vector3(0,0,0);
targetNormalizedVector.x = targetPosition.x - group.position.x;
targetNormalizedVector.y = targetPosition.y - group.position.y;
targetNormalizedVector.z = targetPosition.z - group.position.z;
targetNormalizedVector.normalize()
Then you can use this line anywhere to move the object towards the target position.
group.translateOnAxis(targetNormalizedVector,speed);
This will work similar to the Vector3.MoveTowards function in unity. Just make sure the rotation of the THREE.Group is always set to 0 on x,y and z.

2D screen position from 3D position using three.js

I have some 3D objects within a rotating parent object.
I'm adding a set of 2D "hotspots" which follow these object's screen position. I got this to successfully convert the child object's position to 2D:
// HOTSPOTS //
var v1,m1,p,hotspotX,hotspotY;
v1 = new THREE.Vector3();
m1 = new THREE.Matrix4();
m1 = childObject.matrixWorld;
v1.setFromMatrixPosition(m1);
p = projector.projectVector(v1, camera1);
hotspotX = (p.x + 1) / 2;
hotspotY = (-p.y + 1) / 2;
The problem is that rather than using the child object's origin as the hotspot location, I'd like to set it relative of it, i.e the hotspot's y might be childObject.y-10. I think this needs to happen prior to converting to matrix. Is there a way to do the same as matrixWorld, but from a vector instead of an object?
I could just create extra empty objects for each hotspot and set their positions exactly where I want them, however seeing as the childObjects are already there I'd rather use those if I can. All previous examples I've found use functions which are now deprecated. Hope this makes sense, I'm new to matrices.
Thanks!

How to handle collisions with tile id javascript

Ive written a small game in JavaScript with the html5 canvas and am at the point of collision detection and getting rather confused.
I build my levels in tiled and then import the saved JSON file into the game.
In my level draw function i have a check to see if there are any layer properties and if the layer properties are collisions. If it does, that layer is returned and the loop carries on. When finished, the layer that was returned with collisions gets put through another loop so that the the tile values can be put into an array.
So in this array i have i have a series of arrays depending on how many rows of tiles there are in the layer, and these rows hold the data for that row for each tile.
What i would like to do is when the player x/y is in one of the tiles which doesn't equal 0, then collide.
How would i do this if all i have is the value that is in that tile space?
Here is a link to the live version of the game so you can see for yourself how the tiles are stored, i have put in some console.logs so you might want to use firebug or equivalent to look at that. To log in use
Username - guest
password - guest
TO clarify my question is: How do i create collisions between my player x/y and a tile value??
Thanks very much
UPDATE
Ok so i think im nearly there, my problem at the moment is how do i read the objects x and y out of the array and then check the collision, at the moment the collision detection on works with the last tile in the array (the bottom right of the screen), here is the code i implemented to go through the array:
this.check_coll = function(array,posX, posY){
var collided = false,
block_x,
block_y,
block_cx,
block_cy,
combined_hw = 32,
combined_hh = 32,
player_cx = posX+(32/2),
player_cy = posY+(32/2);
array.forEach(function(value,i){
//get obj x
block_x = value[1];
//get obj y
block_y = value[2];
block_cx = block_x+(32/2);
block_cy = block_y+(32/2);
collided = Math.abs(player_cx - block_cx)< combined_hw
&& Math.abs(player_cy - block_cy)< combined_hh;
});
return collided;
}
Any ideas guys??

Box2d.js with Processing.js

Recently I have been furthering my knowledge of Javascript, by combining the Processing.js and Box2D.js libraries to make some neat browser-based simulations.
With my current idea, I am trying to allow the user to click and drag a shape, and then let it drop once the mouse is released. So far I have been able to figure out how to use the b2MouseJoint object to manipulate a body with mouseX/mouseY coordinates, but it doesn't quite work to the full extent.
All that happens when a shape is clicked is it gets pinned and revolves around what ever mouseX/mouseY point was current at the time of the click.
void mousePressed(){
for(int i = 0; i < circles.size(); i++){
//Get body objects from ArrayList
var obj = circles[i];
// Retrieve shapes from body
var innerShape = obj.GetShapeList();
var rad = innerShape.m_radius;
// Create mouseJoint and add attributes
var mouseJoint = new b2MouseJointDef();
mouseJoint.body1 = world.GetGroundBody();
// Detect body
if(dist(mouseX,mouseY,obj.m_position.x,obj.m_position.y) < rad){
Vec2 p = new b2Vec2(mouseX,mouseY);
mouseJoint.body2 = obj;
mouseJoint.target = p;
mouseJoint.maxForce = 10000.0f * obj.GetMass();
mouseJoint.collideConnected = true;
mouseJoint.dampingRatio = 0;
mouseJoint.frequencyHz = 100;
world.CreateJoint(mouseJoint);
}
}
}
So basically my question is, how can this be written so the Body/Shape follows my mouse's coordinates while I have the mouse held down, instead of just pinning the shape in place.
Cheers
Basically all you have to do is add the code you're using now to set the coordinate in mousePressed to a mouseDragged() method, as well, as this is the event method that gets called while the mouse is moved with one or more buttons depressed:
void mouseDragged()
{
// update obj with mouseX and mouseY in this method
}
You may also want to do a bit more administration by setting up "initial click" mark variables during mousePressed(), updating a set of "offset" variables during mouseDragged() and committing the offsets to the marks in mouseReleased(), so that you can do things like snapping back to the original position, etc.

Categories