Get the dimensions(sizes) of a 3d model with js - javascript

I actually work on AR project with three.js and i handle some 3d models, but I have some problem with the sizes of the models. Because I want them to all have the same size, so I needed to set the same dimensions to all models. I first tried to solve this by using boundingbox and boundingsphere but it doesn't work.
So how can I get the sizes and how can I set the sizes ?

var size = new THREE.Box3().setFromObject( yourObject ).getSize(new THREE.Vector3())

I need somethig else, because the code of manthrax is interesting but have some limits.. for exemple with this code:
andy.scale.set(0.011, 0.011, 0.011);
andy.rotation.set(0, 0, 0);
andy.position.set(0,0,0);
var size = new THREE.Box3().setFromObject(andy).getSize(new THREE.Vector3())
console.log(size);
function moy(vect){
return ((vect.x+vect.y+vect.z)/3);;
}
console.log(moy(size));
andy.scale.set(0.030, 0.030, 0.030);
console.log(moy(size));
If i want to change the value of "size" how can i do that ?
PS: andy is my 3d model
I solve it, i create my own box3:
andy.scale.set(0.011, 0.011, 0.011);
andy.rotation.set(0, 0, 0);
andy.position.set(0,0,0);
var box3d = new THREE.Box3();
var size = box3d.setFromObject(andy).getSize(new THREE.Vector3())
console.log(size);
function moy(vect){
return ((vect.x+vect.y+vect.z)/3);;
}
console.log(moy(size));
andy.scale.set(0.030, 0.030, 0.030);
box3d.setFromObject(andy).getSize(size);
console.log(moy(size));

Related

Animating LineSegments in THREE.js

I have a solid MorphBlendMesh that is overlayed with a LineSegments object using EdgesGeometry/LineBasicMaterial in order to create a wireframe look without the "diagonals" that result from the triangle approach in newer versions of three.js. The problem is that I cannot find a way to get LineSegments to animate along with the mesh, presumably because it isn't a mesh, its simply an Object3D.
Is there a way to animate a LineSegments object with AnimationMixer? Or replicate this same look with a mesh setup that works well with AnimationMixer?
For reference, my question is essentially an expansion of this question -- same idea, but it MUST be capable of animation with AnimationMixer.
You can attach an arbitrary property to the mixer. This property will hold the vertices.
const a: any = ((lines.geometry as THREE.BufferGeometry).attributes.position as BufferAttribute)
.array;
const p: any = (line.geometry as any).attributes.position.array;
(lines as any).value = [...a];
const keyFrame2 = new THREE.NumberKeyframeTrack(
'.value',
[0,1],
[...a, ...p],
THREE.InterpolateSmooth
);
this.lineGeometriesToUpdate.push(lines as THREE.LineSegments);
const clip2 = new THREE.AnimationClip('lines', 1, [keyFrame2]);
const mixer2 = new THREE.AnimationMixer(lines);
const ca2 = mixer2.clipAction(clip2);
this.mixer.push(mixer2);
Then, in your animation loop, you use this property to update the geometry
this.lineGeometriesToUpdate.forEach(l => {
const geom = l.geometry as THREE.BufferGeometry;
const values = (l as any).value;
geom.setAttribute('position', new THREE.BufferAttribute(new Float32Array(values), 3));
(geom.attributes.position as BufferAttribute).needsUpdate = true;
});
this.renderScene();

THREE.Color: Unknown color #002dff (warning/error)

I need to update the color after receiving the value from dat.GUI .
But, this
var colored = new THREE.Color(value.replace("#","0x"));
is throwing this warning "THREE.Color: Unknown color 0x002dff" and the 'colored' isn't updating.
value = #002dff (at that time, it keeps on changing, user input)
Edit: I know I can use this as "THREE.Color( #002dff )", but the color is changing at run time according to the user input from controls I've created using dat.GUI, so I won't be knowing the actual value that can be added to the code.
PS: It was replace() which was causing the problem. It's solved.
You have to give a hexadecimal number, not a string to the Color constructor. Try to call the parseInt function:
var colorValue = parseInt ( value.replace("#","0x"), 16 );
var colored = new THREE.Color( colorValue );
try this ((new THREE.color("#FF00FF")),.if you want to choose a favortie color for your program .check this link out http://www.rapidtables.com/web/color/RGB_Color.htm ,are got to the photoshop and their you can select the color and it shows the color code .
THREE.Color() has the .setStyle() method.
var obj;
var gui = new dat.GUI();
var props = {
color: '#002dff'
};
var colorController = gui.addColor(props, 'color');
colorController.onChange(
function(value){
// uncomment this to see it's working
//var colored = new THREE.Color(value);
//console.log(colored);
obj.material.color.setStyle(value);
}
);
var sphere = new THREE.Mesh(new THREE.SphereGeometry(2, 32, 24), new THREE.MeshStandardMaterial());
sphere.material.color.setStyle("#002dff");
scene.add(sphere);
obj = sphere;
jsfiddle example. three.js r85, dat.GUI 0.6.5
PS Don't use new THREE.Color() to change an exisiting colour of a material, use setXXXXX() methods of THREE.Color()

Updating Cesium Callback Property causes the entity to flash

Here is some code that can be pasted into a Cesium Sandcastle.
It adds an entity to the map, then every second, updates the CallbackProperty for the position property. Each time it is updated the entity flashes.
var viewer = new Cesium.Viewer('cesiumContainer');
var position = new Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0);
var constant = false;
var blueBox = viewer.entities.add({
name : 'Blue box',
position: new Cesium.CallbackProperty(getPos, constant),
box : {
dimensions : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0),
material : Cesium.Color.BLUE
}
});
function getPos() {
return position;
}
function setPosCallback() {
constant = !constant;
blueBox.position.setCallback(getPos, constant);
}
setInterval(setPosCallback, 1000);
Is there a way to update this type of property without causing the entity to flash? Maybe using requestAnimationFrame or something?
I need to use the callbackProperties for drawing shapes, but once they are drawn, I want them to use constant properties. I have also tried changing the isConstant property, but its read only.
I realize this question was from a long time ago, but it looks like the problem is this line "constant = !constant;". Simply removing this will fix the flickering.
Edit: I misunderstood the question, I too have the flicker issue when switching between constants and callbacks.
var viewer = new Cesium.Viewer('cesiumContainer');
var position = new Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0);
var constant = true;
var blueBox = viewer.entities.add({
name : 'Blue box',
position: new Cesium.CallbackProperty(getPos, constant),
box : {
dimensions : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0),
material : Cesium.Color.BLUE
}
});
var count = -114.0;
function getPos() {
count+=0.2;
return new Cesium.Cartesian3.fromDegrees(count, 40.0, 300000.0);
}
function setPosCallback() {
constant = !constant;
blueBox.position.setCallback(getPos.bind(blueBox), true);
}
setInterval(setPosCallback, 1000);
hi, the box is moving and it didnt flash in my browser when i bind the callback function to the entity and kept constant = true.
you might want to try again. cheers

Trouble in writing a small library in JavaScript

I'd been trying to write a small library in Javascript mainly for Canvas drawImage() method.
The main purpose of the library is to pass array values instead of passing single values such as :
// srcPos=[0,0] , size=[90,90], dstPos=[50,50]
function draw_image(context, image, srcPos, size, dstPos, size) {
context.drawImage(image, srcPos[0], srcPos[1], size[0], size[1], dstPos[0], dstPos[1], size[0], size[1]);
}
but when i called this function jzz like this, I'm getting Uncaught ReferenceError :
var canvas = document.getElementById("display"),
frame = canvas.getContext("2d");
var shipInfo = { center:[45, 45], size:[90, 90], radius: 35, angle:45 },
shipImage = new Image(),
pos = [40, 70];
shipImage.src = "ship.png";
function draw() {
draw_image(frame, shipImage, shipInfo.size, pos, shipInfo.size);
}
window.onload = function() {
draw();
}
And Is it possible to implement a method overriding the default drawImage() like this:
frame.draw_image(shipImage, srcPos, shipInfo.size, dstPos, shipInfo.size);
If you want to add a function to the 2d context, javascript makes this easy thanks to the prototype inheritance : You can inject the Context2D object to add or change its function as you wish.
You might want to look at a few addings i made to the context in a small canvas lib i made here : https://github.com/gamealchemist/CanvasLib
Some will tell that injecting is evil, but unless you're on a huge boat i would just say : If you use some graphic library, respect the semantic of existing functions and everything should be fine. If you don't use libs : do whatever it takes !
So, to answer more specifically to your question, your shorter drawImage would give :
CanvasRenderingContext2D.prototype.draw_image = function ( image,
srcPos, size,
dstPos, size) {
this.drawImage(image, srcPos[0], srcPos[1], size[0], size[1],
dstPos[0], dstPos[1], size[0], size[1]);
};
Then you can use the new function on all your contexts :
var canvas = document.getElementById("display"),
frame = canvas.getContext("2d");
frame.draw_image( ... ) ;
Notice that you could use 'rect' objects, which would be arrays with 4 elements, x, y, w, h, and lead to an even shorter syntax.
Edit : i see in your lib that you want to rotate your rect.
First thing is that you don't want to reset the transform. Just save it then restore it.
I would try something closer to this :
var x = dstPos[0],
y = dstPos[1],
halfWidth = dstSize[0]*0.5, // !! not src use >>1 if you know it's an int.
halfHeight = dstSize[1]*0.5, // !! not src ...
angleInRads = angle * Math.PI / 180;
this.save();
this.translate(x+halfWidth,y+halfHeight);
this.rotate(angleInRads);
this.drawImage(image
, center[0], center[1], srcSize[0], srcSize[1]
, -halfWidth, -halfHeight, dstSize[0],dstSize[1]);
this.restore();
Your small image library would fit well inside a javascript object.
A Demo: http://jsfiddle.net/m1erickson/7pZJw/
A javascript object can hold information about your image:
the image itself
the image size (can be automatically calculated for you)
the image centerpoint (can be automatically calculated for you)
Example:
// create a new object
// fill it with the info about the image
var object={
image:shipImage,
width:shipImage.width,
height:shipImage.height,
centerOffsetX:shipImage.width/2,
centerOffsetY:shipImage.height/2,
radius:35,
angle:45,
};
A javascript object can also hold functions that draws the image (as you've done in your code)
Example:
// when you call object.draw the image will be drawn by this function
// which is added to the object itself
draw:function(context,atX,atY,newWidth,newHeight){
context.drawImage(
this.image,
0,0,this.width,this.height,
atX,atY,newWidth,newHeight);
},
A function to create your small image library inside a javascript object might look like this:
function createImageObject(image,radius,angle){
// create a new object
// fill it with the info about the image
var object={
image:image,
width:image.width,
height:image.height,
centerOffsetX:image.width/2,
centerOffsetY:image.height/2,
radius:radius,
angle:angle,
draw:function(context,atX,atY,newWidth,newHeight){
context.drawImage(
this.image,
0,0,this.width,this.height,
atX,atY,newWidth,newHeight);
},
};
return(object);
}
And you can use your ship object library like this:
// create a new ship object
var shipObject=createImageObject(img,35,45);
// draw the ship image using the ship object
// draw at 20,20 with size 75,75
shipObject.draw(frame,20,20,75,75);
BTW, I see you're using the version of drawImage that will scale/clip the source image.
If you just want to draw the full image at its original size you can do this shortcut:
// draw the image full-sized at x,y
context.drawImage(image,x,y);

Changing face colors during run-time in Three.js on a model imported from blender

I've imported a model of a soccer ball (truncated icosahedron) from blender (via JSON loader) and I wanted to change the face colors upon clicking. The faces are correctly identified I can change the color of the entire model but not particular faces. I have dug a bit deeper and I found that the colors are correctly assigned to soccerball.geometry.faces[i] but the new face colors are not shown.
I've gone through all of the similar threads and tried all of the proposed solutions (different materials, dirtyColors, dynamic, colorsNeedUpdate, etc.) but nothing helped.
this is how I import the model:
var loader = new THREE.JSONLoader( );
var onGeometry = function(geom) {
soccer = new THREE.Mesh( geom, new THREE.MeshLambertMaterial());
soccer.position.set( 0, 0, 0 );
soccer.scale.set( 2, 2, 2 );
soccer.geometry.dynamic = true;
soccer.geometry.dirty = true;
soccer.overdraw = true;
objects.push(soccer);
scene.add(soccer);
};
loader.load("models/model.js", onGeometry);
Can you please help me? thanks in advance
soccer.material.vertexColors = THREE.VertexColors ;
or
soccer.material.vertexColors = THREE.FaceColors;
If that doesn't work then I'll need to havre the model itself to do some tests.

Categories