Three.js Raycaster collision detection with spheres - javascript

I was working with an example from a previously answered question here: Three Js Object3D Button Group Detect Single Object Click While Mouse Movement Causes Object3D Button Group Zoomi
I was making some changes to make it work the way I wanted, and ran into a few issues that I am having trouble figuring out.
Here is my jsbin: http://jsbin.com/agadiw/1/
1) I switched the objects from CubeGeometry to SphereGeometry and the collisions are not as accurate, it seems like I can only click on certain parts of the spheres to trigger a collision. The spheres are the same size as the cubes were, also sometimes when I click outside a sphere it triggers a collision. I alert a number unique to the sphere on collision.
Is there some kind of setting or position I have wrong?
2) When a sphere is clicked on, I try to change its color to red, however all the sphere's colors change to red, not just the one clicked on. I looked at what the intersects array is when sphere is clicked, and it only returns the one clicked on, I have no idea why it changes all of them.
3) Lastly, I have been looking for good resources, tutorials, examples, that are up to date or have good explanations of how things are working, but I haven't really found any I tried the official documentation, but a lot of sections just say 'todo'. I was just wondering if anyone had any just resources they could lead me to to help me learn this stuff.
Thanks for any help.

1) The CSS margin must be zero in your case.
body { background: black; margin: 0; overflow: hidden }
Alternatively, you can see the answer to this question.
2) The color of all the objects changes because all your objects are sharing the same material. Do this instead:
ButtonsMesh = new THREE.Mesh( ButtonsGeometry, new THREE.MeshBasicMaterial() );
3) You are going to have to learn three.js by studying the examples and perusing message boards. Also have a look at this answer for additional tips.

You are using intersectObjects() to check the intersection. However the intersection therefore includes all those objects. To fix it you need to loop through the objects with intersectObject() instead
for (var i=0; i<=(objects.length-1); i++) {
var intersect = raycaster.intersectObject(objects[i]);
if (intersect.length > 0) {
//change the color here
break; //important to break the loop
}
}
As for documentation; These are good examples. But currently it's mainly digging through sourcecode and github to find what you need

Related

How would I add text in a circle and also shuffle my questions?

Link to code for reference: https://editor.p5js.org/tpant963/sketches/Ft9fBLlRU
Hi! So I've been trying to make a review game on Java OOP concepts on p5.js, but I'm beginning to get a bit overwhelmed because this is my very first p5.js project. How the game works is that there is a question printed on the screen with bubbles floating around that are supposed to have word associations on them. If the correct bubble is clicked then it will turn green and if it is incorrect, it will turn red. The round ends when all the correct bubbles are clicked.
My first problem is that I can't make the text appear on the bubbles. I tried doing it like this (using the correct array as an example) but it resulted in my bubbles and text one the screen getting very messed up, not to mention, the text never showed up.
textAlign(CENTER, CENTER);
for (let i = 0; i < correct.length; i++) {
ellipse(correct[i].x, correct[i].y,
correct[i].r, correct[i].r);
textSize(correct[i].r);
text(correct[i].q1C, correct[i].x, correct[i].y); }
My second issue lies in the fact that I'm unsure of how to shuffle the questions and keep the game going until all the questions are done.
Thanks!
Well, for the shuffling you could use the built in p5.js function:
shuffle(Arr)
and then just keep count of how many questions you have:
let questionCount
function newQuestion(){
questionCount++
questionArr[questionCount]
}
or something close to that; haven't looked thru your project all that much

Three.js: Panorama Cube to Zoom In and Transition Into a Different Panorama Cube

I am new to Three.js. I am using this example with 6 image cube for panorama effect, where one can pan, zoom in and out around cubes.
https://threejs.org/examples/?q=panorama#webgl_panorama_equirectangular
I want to figure out how, at maximum zoom-in level, I can transition user into a different panorama cube (with different image source), mapped to this particular cube part. So I would, sort of, open the next scene to take user further to the next level in his journey.
This is nearly what Google Street View does when you click on arrows to move forward down the road.
I do not see many examples out there. I researched and saw this may be possible with creating 2 scenes? Any ideas how to make it functional I would appreciate.
Detecting WHEN to transition:
In the example given, the mouse events are all given. The zoom is handled in onDocumentMouseWheel by adjusting the camera's fov property. "Zoom In" reduces the fov, and "Zoom Out" increases it. It would be trivial to detect when the fov has reached a minimum/maximum value, which would trigger your transition to a new scene.
Detecting WHERE to transition:
The next step is determining into which new scene you will transition. You could do something hotspot-like, where you shoot a ray from the camera to see if it hit a particular place (for example a THREE.Sphere which you have strategically positioned). But for simplicity, let's assume you only have the 6 directions you mentioned, and that you're still using the example's mouse control.
Camera movement is handled in onDocumentMouseMove by updating the lat and lon variables (which appear to be in degrees). (Note: It seems lon increases without bounds, so for clarity it might be good to give it a reset value so it can only ever be between 0.0-359.99 or something.) You can get all math-y to check the corners better, or you could simply check your 45's:
if(lat > 45){
// you're looking up
}
else if(lat < -45){
// you're looking down
}
else{
// you're looking at a side, check "lon" instead
}
Your look direction determines to which scene you will transition, should you encounter your maximum zoom.
Transitioning
There are lots of ways you can do this. You could simply replace the texture on the cube that makes up the panorama. You could swap in a totally different THREE.Scene. You could reset the camera--or not. You could play with the lights dimming out/in while the transition happens. You could apply some post-processing to obscure the transition effect. This part is all style, and it's all up to you.
Addressing #Marquizzo's concern:
The lighting is simply a suggestion for a transition. The example doesn't use a light source because the material is a MeshBasicMaterial (doesn't require lighting). The example also doesn't use scene.background, but applies the texture to an inverted sphere. There are other methods one can use if you simply can't affect the "brightness" of the texture (such as CSS transitions).
I added the following code the the example to make it fade in and out, just as an example.
// These are in the global scope, defined just before the call to init();
// I moved "mesh" to the global scope to access its material during the animation loop.
var mesh = null,
colorChange = -0.01;
// This code is inside the "update" function, just before the call to renderer.render(...);
// It causes the color of the material to vary between white/black, giving the fading effect.
mesh.material.color.addScalar(colorChange);
if(mesh.material.color.r + colorChange < 0 || mesh.material.color.r + colorChange > 1){ // not going full epsilon checking for an example...
colorChange = -colorChange;
}
One could even affect the opacity value of the material to make one sphere fade away, and another sphere fade into place.
My main point is that the transition can be accomplished in a variety of ways, and that it's up to #Vad to decide what kind of effect to use.

Make a multi-part "fluid body" act as one single body

I am using Phaser.js and its p2 physics in order to simulate what "fluid bodies". You can see in this example that a kind of fluid body is created (credits to John Watson). The only possible interaction is with mouse movement.
I have noticed some interesting properties that could probably help me getting what I pretend which are restitution, gravity and damping. All of these are in included in the shown example.
// Add a force that slows down the droplet over time
droplet.body.damping = 0.3;
// Add bounciness and gravity
this.game.physics.p2.restitution = 0.8;
this.game.physics.p2.gravity.y = 250;
After some research and reflexion I concluded that the body I seek must be more united than the example body which means that, within certain limits, a force with the direction of the center of the body (center +- top of body) should be applied to all the "small bodies" that make the body. I suppose that after achieving that even if I move the entire body with cursors it will move all together. The overall efect I want is a pile-type body form (less mass on upper part and more mass on the bottom part):
The only way for the body to lose mass should be an external force applied to the body that surpasses the resistance force that keeps the body united.
Even after researcing for quite a while I seem very lost in the matter...
Should I literally opt for p2 forces ( I believe that exists ) ?
Should I use springs to connect all the small bodies? (springs)
How would I always get the "center of the body"?
Thanks.
Disclaimer: I have not used Phaser.js, so I can't help you with the framework. I will however try to share some of my ideas on the problem, and hopefully it helps you.
I recently wrote this answer regarding plasticity (which could be of interest to you), but what you want is slightly different.
The simulation
First, lets talk some about the simulation you showed. You write "fluid bodies", but from what I see in the code example is nothing fluid -- it's a pure particle simulation with "cheated" physics features that comes from (1) the automatic damping of the particles and (2) the restitution which in normal speak means how elastic a collision with the object is (e.g. the 0.8 value in this case means that 20% of the kinetic energy is lost with every collision). So basically, we have a particle simulation with a lot of damping.
That this yields something that looks 'fluid like' is really pretty cool, but my guess is that this is also due to the rendering (e.g. show the particles as small disks instead of the blurred thing and it will look a lot more like what you'd expect).
Your questions
Should I literally opt for p2 forces ( I believe that exists ) ?
I am actually not sure what this means, but I'm guessing it's Phaser related.
Should I use springs to connect all the small bodies? (springs)
No. If you use a elastic potential to calculate the force you will get an elastic body as differing from plasticity which is what you're looking for. What other function you use will entirely determine the behaviour of your simulation, so going with this idea there will be a lot of experimentation.
If x_cm is the position (vector) to the center of mass, and x[i] is the position of particle i, then one example could be:
F(i) = F_constant*(x_cm - x[i])
A purely linear function. F_constant is some (constant) coefficient. Particles far away will receive a greater force than particles nearby. You would then calculate this force for all particles, and apply it accordingly.
How would I always get the "center of the body"?
The center of mass of the body is straight forward to calculate. In pseudo code it looks like this:
var x_cm
var total_mass = 0
for each particle p:
total_mass += p.mass()
x_cm += p.mass()*p.position()
x_cm /= total_mass
Formulas are hard to display nicely here, but it's just the same as described on wikipedia.
Another possibility
This answer is already long, but just a finishing thought. From my perspective it sounds like you want something similar to sand (i.e. it is a particle simulation similar to the one you showed, but it piles as well). A common way to simulate sand is by the exact simulation as you have above, but with friction added to the particles. If this is possible to do with Phaser I don't know, but I would expect it being easy to do.
EDIT: Had a typo in the last sentence. Simulating sand with Phaser, by adding friction to the example simulation, should be easy.

update the canvas scene when reaching it's width

this is a general question in building a game let's say i am building a game that it is not build under one and only scene but multiple continuous scenes. what is the best way to switch between those scene when the player reach the width of the canvas
pseudo code
var scene= 0;
function DrawScene(scene){
if(player.width >= CanvasWidth){
player.x= 0;
Scene.draw(scene);
scene++;
}
}
function UpdateWorld(){
DrawScene(scene);
}
this is just a pseudo code of how i thought about it i don't know how this is made in real life game can anyone give me a hint or show me some link that can describe this ? thank you
I think the best way to handle scene switching in a quite general case would be to handle some objects, let's call them switchers, that may have a visual or not ( => it's an invisible door or not), and which will switch scene when the hero overlaps them.
You'll soon want to add conditions to the switch (the hero has this key, is equipped with this weapon, ...).
And the switch should happen only if there's only 'enough' overlap, which could mean, say, that more than 50% of the bounding box of the hero is on top of the door.
For the pseudo-code, there are may ways to do a game loop, but at some point you'll have to do :
for each switch in switches {
if ( overlap( hero, switch ) && switch.canSwitch(hero) ) scene = switch.scene ;
}
i did a very small demo to demonstrate.
It is using my all-purpose fiddle as a base, so there's a bit of mess here :-) :
http://jsfiddle.net/gamealchemist/bC5JL/
use arrow keys and you will switch between two 'scenes' when overlapping the doors.

Three.js constrain object drag to surface of another object

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.

Categories

Resources