threejs modify envMap on mouseover - three.js

Im new in threejs, I want to learn some about this library... but, in my opinion, there is very little documentation.
Issue is:
I have a SphereGeometry and I want to give It some interactivity through mouse events, I'm using three.domevent.object3d.js for "mouseover" and "mouseout" events to make scale property bigger or smaller. But I can not to modify sphere material when mouseover is triggered because nothing happens. My code is:
sphere.on('mouseover', function(event){
event.target.scale.x *= 2;
event.target.scale.y *= 2;
event.target.scale.z *= 2;
event.target.material.envMap = textureCube;
event.target.material.combine = THREE.MixOperation;
event.target.material.reflectivity = 0.15;
}).on('mouseout', function(event){
event.target.scale.x *= 0.5;
event.target.scale.y *= 0.5;
event.target.scale.z *= 0.5;
event.target.material.envMap = null;
event.target.material.combine = THREE.MixOperation;
event.target.material.reflectivity = 0;
});
textureCube is a bunch of jpegs for skyboxMesh, its code is:
var r = "images/";
var urls = [ r + "px.jpg", r + "nx.jpg",
r + "py.jpg", r + "ny.jpg",
r + "pz.jpg", r + "nz.jpg" ];
textureCube = THREE.ImageUtils.loadTextureCube( urls );
Any help will be appreciated
Thanks

If you want to add or remove an environment map from a material, you will have to add
material.needsUpdate = true;
Have a look at the "How to update things" doc: https://threejs.org/docs/index.html#manual/en/introduction/How-to-update-things
three.domevent.object3d.js is not part of the library, so I can't comment on that.
three.js r.52

Related

I have a question about using turtle graphic functions and looping methods on p5.js

I have to create these two included images using the turtle function and the loop method on p5js and I am struggling I was given https://editor.p5js.org/dpapanik/sketches/_lbGWWH6N this code on p5js as a start please help, thanksenter image description here
So I've played around with some of the stuff for awhile, and I've created two functions. One that makes a single quadrant of the first problem, and one that creates a single wiggly line for the second problem. This is just a base for you to work of in this process. Here's each of the functions. Also, note that each of them takes in the turtle as a parameter:
function makeLineQuadrant(turtle) {
// this currently makes the top left corner:
let yVal = windowWidth * 0.5;
let xVal = windowWidth * 0.5;
for (let i = 0; i < 13; i++) {
// loop through the 12 lines in one quadrant
turtle.face(0); // reset for the new round
turtle.penUp();
let startLeft = i * ((windowWidth * 0.5) / 12); // decide which component on the button we should start at
let endTop = (12 - i) * ((windowWidth * 0.5) / 12); // how far down the y-axis should we go? You should write this out on paper to see how it works
turtle.goto(startLeft, yVal);
turtle.penDown();
let deg = turtle.angleTo(xVal, endTop); // what direction do I need to turn?
turtle.face(deg);
let distance = turtle.distanceTo(xVal, endTop); // how far away is it?
turtle.forward(distance);
}
}
I tried to add a few comments throughout, but if there is any step that is confusing, please add a comment.
function makeSquiggle(turtle) {
turtle.setColor(color(random(0, 255), random(0, 255), random(0, 255)));
let middleX = windowWidth * 0.5, middleY = windowHeight * 0.5;
turtle.goto(windowWidth * 0.5, windowHeight * 0.5);
// let's start moving in a random direction UNTIL our distance from the center is greater than some number X
let X = 300; // arbitrary distance from center
// some variables that can help us get some random movement for our turtle:
let turtleXvel = random(-3, 3), turtleYvel = random(-3, 3);
while (turtle.distanceTo(middleX, middleY) < X) {
turtle.face(0);
// calculate movement:
let newXmove = turtle.x + turtleXvel, newYmove = turtle.y + turtleYvel;
// direct our turtle:
turtle.face(turtle.angleTo(newXmove, newYmove));
let distance = turtle.distanceTo(newXmove, newYmove); // how far away is it?
// move our turtle
turtle.penDown();
turtle.forward(distance);
// change the velocity a little bit for a smooth curving:
turtleXvel += random(-1, 1);
turtleYvel += random(-1, 1);
}
}
Note that I'm changing the velocities instead of the position directly. This is a classic Calculus / Physics problem where the derivative gives us a smaller range, so adjusting turtleXvel and turtleYvel change the position in much less drastic ways versus:
turtle.x += random(-1, 1);
turtle.y += random(-1, 1);
You should look at the difference as well to visualize this. Beyond this is working with these structural components to finish this up!

Three.js issue at edges of tiled texture using MeshFaceMaterial

I am trying to tile the texture from multiple images onto a plane geometry using MeshFaceMaterial. Every thing works fine, except for a blurry edge forming in between tiles.
.
var textureArray = [];
var tileColumns = 2;
var tileRows = 1;
textureArray[0] = THREE.ImageUtils.loadTexture('./test3.jpg');
textureArray[1] = THREE.ImageUtils.loadTexture('./test4.jpg');
var faceCountPerTileX = 2 * widthSegments/tileColumns;
var faceCountPerTileY = heightSegments/tileRows;
var faceCountX = 2 * widthSegments;
var faceCountY = heightSegments;
for(var tileIndexY = 0; tileIndexY < tileRows; tileIndexY++){
for(var tileIndexX = 0; tileIndexX < tileColumns; tileIndexX++){
var index = tileIndexY * tileColumns + tileIndexX;
textureArray[index].wrapS = THREE.RepeatWrapping;
textureArray[index].wrapT = THREE.RepeatWrapping;
textureArray[index].repeat.set(tileColumns,tileRows);
materialContainer[tileIndexY * tileColumns + tileIndexX] = new THREE.MeshBasicMaterial({
map: textureArray[tileIndexY * tileColumns + tileIndexX],
overdraw: true,
ambient: 0xffffff
});
for(var faceIndexY = tileIndexY * faceCountPerTileY; faceIndexY < (tileIndexY+1) * faceCountPerTileY; faceIndexY++){
for(var faceIndexX = tileIndexX * faceCountPerTileX; faceIndexX < (tileIndexX+1) * faceCountPerTileX; faceIndexX++){
g.faces[faceIndexY * faceCountX + faceIndexX].materialIndex = tileIndexY * tileColumns + tileIndexX;
}
}
}
}
var mat = new THREE.MeshFaceMaterial(materialContainer);
var obj = new THREE.Mesh(g, mat);
I have tried all known solutions, i have even tried writing a custom shader and using ShaderMaterial. But no luck, can some help me out to fix the issue?
By the looks of it, you set the texture mode of the invidual textures in your set to repeat.
This seems wrong, the individual textures do not repeat, they are displayed only once. Setting a texture to repeat causes the right side of the texture to "blend through" on the left (and vice versa), causing visible seams like the one on your screenshot.

Setting color of mapped image for ThreeJS particles

Originally I was using ParticleSystem, but I discovered that Raycaster does not work with it. So I'm now modifying my code to simply use individual Particle objects.
The problem is, I can't seem to set the color of the image I'm mapping to the particles like I was able to with ParticleSystem.
I tried the following:
texture = THREE.ImageUtils.loadTexture("ball.png");
material = new THREE.ParticleBasicMaterial({
size : 10,
color: 0x00C1BF,
map : texture,
transparent : true,
});
// Generate some random points...
for (var i = 0; i < pointCount; i++) {
var particle = new THREE.Particle(material);
particle.position.x = Math.random() * (max - min) + min;
particle.position.y = Math.random() * (max - min) + min;
particle.position.z = Math.random() * (max - min) + min;
particle.scale.x = particle.scale.y = particle.scale.z = 3;
plot.add(particle);
}
But the color of ball.png remains the same. If I comment out the image I'm mapping to the points, the colors are changing. But it's not working with the mapped image. When I was using ParticleSystem, inside the for loop where I generate the points, I was adding this:
colors[i] = new THREE.Color(0xffffff);
colors[i].setHSL((x + 1000 ) / 2000, 1, 0.5);
And then set particleSys.colors = colors; outside the loop. That changed the color of the points, but this doesn't seem to work with Particle.
I hate to keep bugging the community with questions like this, but I really would appreciate any guidance on this. Many thanks, as always! :)
Also, here's a link to ball.png that I'm using: http://threejsdoc.appspot.com/doc/three.js/examples/textures/sprites/ball.png

Add easing to the rotation of an image on mouse position

Sorry for the English.
I'm trying to add a "ease-out-elastic" movement of rotation, but I can not.
The code on which I am trying is http://jsfiddle.net/22Feh/5/.
Thanks
var img = $('.image');
if(img.length > 0){
var offset = img.offset();
function mouse(evt){
var center_x = (offset.left) + (img.width()/2);
var center_y = (offset.top) + (img.height()/2);
var mouse_x = evt.pageX; var mouse_y = evt.pageY;
var radians = Math.atan2(mouse_x - center_x, mouse_y - center_y);
var degree = (radians * (180 / Math.PI) * -1) + 90;
img.css('-moz-transform', 'rotate('+degree+'deg)');
img.css('-webkit-transform', 'rotate('+degree+'deg)');
img.css('-o-transform', 'rotate('+degree+'deg)');
img.css('-ms-transform', 'rotate('+degree+'deg)');
}
$(document).mousemove(mouse);
}
The easing calculations needs to be done using a timer. This can be complex, however there are many libraries out there that take care of this for you. Take a look at GSAP for starters.
Using your code I've created the jsfiddle below. You can see that all I have done is replace your css code transform code with a TweenMax function and added the ease.
TweenMax.to(img, 1, {rotationZ:degree, ease:Elastic.easeOut});
http://jsfiddle.net/Boolean/PNvgt/
Then if you want to take it a step further there is the GreenSock Draggable library.
http://www.greensock.com/draggable/

Smart Centering and Scaling after Model Import in three.js

Is there a way to determine the size and position of a model and then auto-center and scale the model so that it is positioned at the origin and within the view of the camera? I find that when I import a Collada model from Sketchup, if the model was not centered at the origin in Sketchup, then it is not centered in three.js. While that makes sense, it would be nice to auto-center to origin after importing.
I've seen some discussion in the different file loaders about getting the bounds of the imported model, but I have been unable to find any references to how to do that.
The scaling issue is less important, but I feel like it relates to a bounds function, which is why I asked it too.
EDIT:
More info after playing around a bit and a few more google searches...
The code for my callback function on loading the collada file now looks like this:
loader.load(mURL, function colladaReady( collada ) {
dae = collada.scene;
skin = collada.skins[ 0 ];
dae.scale.x = dae.scale.y = dae.scale.z = 1;
dae.updateMatrix();
//set arbitrary min and max for comparison
var minX = 100000;
var minY = 100000;
var minZ = 100000;
var maxX = 0;
var maxY = 0;
var maxZ = 0;
var geometries = collada.dae.geometries;
for(var propName in geometries){
if(geometries.hasOwnProperty(propName) && geometries[propName].mesh){
dae.geometry = geometries[propName].mesh.geometry3js;
dae.geometry.computeBoundingBox();
bBox = dae.geometry.boundingBox;
if(bBox.min.x < minX) minX = bBox.min.x;
if(bBox.min.y < minY) minY = bBox.min.x;
if(bBox.min.z < minZ) minZ = bBox.min.z;
if(bBox.max.x > maxX) maxX = bBox.max.x;
if(bBox.max.y > maxY) maxY = bBox.max.x;
if(bBox.max.z > maxZ) maxZ = bBox.max.z;
}
}
//rest of function....
This is generating some interesting data about the model. I can get an overall extreme coordinate for the model, which I'm assuming (probably incorrectly) would be close to an overall bounding box for the model. But trying to do anything with those coordinates (like averaging and moving the model to the averages) generates inconsistent results.
Also, it seems inefficient to have to loop through every geometry for a model, is there a better way? If not, can this logic be applied to other loaders?
You can use THREE.Box3#setFromObject to get the bounding box of any Object3D, including an imported model, without having to loop through the geometries yourself. So you could do something like
var bBox = new THREE.Box3().setFromObject(collada.scene);
to get the extreme bounding box of the model; then you could use any of the techniques in the answers that gaitat linked in order to set the camera position correctly. For instance, you could follow this technique (How to Fit Camera to Object) and do something like:
var height = bBox.size().y;
var dist = height / (2 * Math.tan(camera.fov * Math.PI / 360));
var pos = collada.scene.position;
camera.position.set(pos.x, pos.y, dist * 1.1); // fudge factor so you can see the boundaries
camera.lookAt(pos);
Quick fiddle: http://jsfiddle.net/p19r9re2/ .
try geometry.center()
center: function () {
var offset = new Vector3();
return function center() {
this.computeBoundingBox();
this.boundingBox.getCenter( offset ).negate();
this.translate( offset.x, offset.y, offset.z );
return this;
};
}(),

Resources