I've imported a collada file from Cinema4D with a tree of parented objects. When I get an object's world position like so:
var thing = scene.getObjectByName("thing");
thing.updateMatrixWorld();
var worldPos = new THREE.Vector3();
worldPos.setFromMatrixPosition(thing.matrixWorld);
it is the same as thing.position, which the docs say is local position. I know this object has a parent with a non-zero position. When I try the same thing without updateMatrixWorld(), the world position is zero. How can I get the correct world position?
I needed to updateMatrixWorld() for each parent of my object, which I did like this:
function updateWorldMatrices (object)
{
var parent = object;
while (parent.parent != null)
{
parent.updateMatrixWorld();
parent = parent.parent;
}
}
Related
I can get the dbId of all items in the Viewer via
const tree = viewerApp.myCurrentViewer.model.getData().instanceTree;
const dbIndices = Object.values(tree.nodeAccess.dbIdToIndex).slice(1);
But for models imported from Revit, their number is much larger than the actually visible objects in the Viewer (for example, for a project consisting of only three walls, this number is approximately 3,500). How do I get a dbId of only visible objects?
By default all nodes (assets to render for Viewer) are visible when a model is loaded. Each node can be uniquely identified by an unique dbid in addition to its externalId that corresponds to the UniqueID of a Revit component.
So the extra dbids that you observed are actually parent nodes. To isolate them, see here to traverse all the leaf nodes (that is nodes representing a single visible components):
function getAllLeafComponents(viewer, callback) {
var cbCount = 0; // count pending callbacks
var components = []; // store the results
var tree; // the instance tree
function getLeafComponentsRec(parent) {
cbCount++;
if (tree.getChildCount(parent) != 0) {
tree.enumNodeChildren(parent, function (children) {
getLeafComponentsRec(children);
}, false);
} else {
components.push(parent);
}
if (--cbCount == 0) callback(components);
}
viewer.getObjectTree(function (objectTree) {
tree = objectTree;
var allLeafComponents = getLeafComponentsRec(tree.getRootId());
});
}
I am Facing this Problem, my randomPoints array element is getting replaced by push method.
Here is the output of my Console
I don't know why this is happening but if I don't use randomPoint.add, it dosen't replaces and work fine.
randomPoint.add retuns the same Vector object as it would return without it.
var hw
var center
var randomPoints = []
var pointWidth = 20
var points = 300
centerCircleWidth = 300;
pointsOffset = 10
function setup(){
hw = createVector(600,500)
createCanvas(hw.x,hw.y)
center = createVector(hw.x/2,hw.y/2)
var randomPoint = createVector(0,0)
randomPoints.push(randomPoint)
randomPoint = p5.Vector.fromAngle(-radians(120), random(centerCircleWidth/2-pointWidth,centerCircleWidth/2-pointsOffset))
randomPoints.push(randomPoint)
console.log(randomPoint)
randomPoint = randomPoint.add(p5.Vector.fromAngle(radians(60), random(pointsOffset,2*pointsOffset)))
// this here replaces the last element of array by itself and add another element of same type.
randomPoints.push(randomPoint)
console.log(randomPoint)
console.log(randomPoints)
}
function draw(){
translate(center.x, center.y)
background(51);
strokeWeight(0)
fill(255)
ellipse(0,0, centerCircleWidth, centerCircleWidth)
for(i=0;i<randomPoints.length;i++){
fill(10)
ellipse(randomPoints[i].x,randomPoints[i].y,pointWidth,pointWidth)
}
}
Your problems looks to be an object reference problem. The third push isn't replacing the previous element in the array, but you are updating the reference which the array is holding, therefore the element in the array is being updated.
If you remove the third push, you will see that the second item in the array will still be updated.
What you need to do is either create a copy of randomPoint and then make a change to it, or create a new variable.
Take a look at this SOF answer which should make it clearer.
I have an svg map with several points where I want to store the initial position of each point in an array. And each point has it's own ID, like point_1, point_2 etc.
I have attached a click handler to each of these and run a function when they are clicked.
So what I want to do in this function is to check if the array already contains the information of the clicked element. If it doesn't, I want to create it.
This is what I want to do, in pseudo code
var arrPoints = [];
zoomToPoint('point_1');
function zoomToPoint(data_id) {
// Does array already contain the data?
if (!arrPoints.data_id) {
// Add data to the array
arrPoints.data_id.clientX = somevalue;
arrPoints.data_id.clientY = somevalue;
}
}
This would basically create an array that looks like this:
arrPoints.point_1[]
arrPoints.point_2[]
Where I can access the data in each .point_1 and .point_2.
But I can't create an array based on a variable, like this:
arrPoints.data_id = [];
Because I end up with data_id as the actual name, not the variable that data_id actually is. So how is this usually accomplished? How can I identify each point to the actual array?
Sorry for my lack of basics
Just use an object:
var arrPoints = {};
zoomToPoint('point_1');
function zoomToPoint(data_id) {
// Does array already contain the data?
if (!arrPoints[data_id]) { // square brackets to use `data_id` as index
// Add data to the array
arrPoints[data_id] = {};
arrPoints[data_id].clientX = somevalue;
arrPoints[data_id].clientY = somevalue;
}
}
How do I get the world rotation of an Object3D in three.js?
I know how to get the world position of an Object3D from object.matrixWorld, but how do I get the world rotation of an object?
I need this for the following problem: I have a hierarchical Object structure like this:
var obj1 = new THREE.Object3D();
obj1.x = 200;
obj1.rotation.x = 0.1;
scene.add(obj1);
var obj2 = new THREE.Object3D();
obj2.y = -400;
obj2.rotation.y = 0.21;
obj1.add(obj2);
var obj3 = new THREE.Object3D();
obj3.z = -200;
obj3.rotation.x = 0.1;
obj3.rotation.y = -0.1;
obj2.add(obj3);
Now I want to make my camera look at obj3 orthogonally in a certain distance. When My Objects are not rotated, this works like this:
var relativeCameraOffset = new THREE.Vector3(0, 0, 500); // 500 is z-distance from my object
var cameraOffset = relativeCameraOffset.applyMatrix4(obj3.matrixWorld);
camera.position = cameraOffset;
When only my last child is rotated I get what I want when I add this line
camera.rotation = obj3.rotation;
But when all parent Elements are rotated this is not working. So I'm looking for a way to get the world "orientation" of my 3D object.
Thanks.
One way to get the "world" rotation is as follows:
const position = new THREE.Vector3(); // create one and reuse it
const quaternion = new THREE.Quaternion();
const scale = new THREE.Vector3();
mesh.matrixWorld.decompose( position, quaternion, scale );
You can then set your camera orientation like so:
camera.quaternion.copy( quaternion );
Important: if you are going to access matrixWorld directly, you have to make sure it is updated. The renderer typically does this for you in the render loop. If, however, you are between render calls, and need to force an update of the matrix, you can do so with
mesh.updateWorldMatrix( true, false );
EDIT: There is another method that is now available. Check the source code so you see what it is doing.
Object3D.getWorldQuaternion( targetQuaternion );
three.js r.147
If you just want to link camera with obj3, you can just do this:
obj3.add(camera);
Use mesh.getWorldPosition() to get world position, and mesh.getWorldRotation() to get it's rotation.
I'm currently working on drawing up a tilemap using a set of images loaded inn to an array.
I've defined a tile as an object like this:
function tile(gfx){
this.tile = gfx;
this.drawSelf = function(x,y)
this.tile.x = x;
this.tile.y = y;
}
Then I filled up an array with several tile objects which through the debugger displays correctly.
Now when I start drawing up the images using this code:
for (var x = 0; x < mapArray.length; x++){
xN = 183 + (50*x);
mapArray[x].drawSelf(xN, 134);
gameStage.addChild(mapArray[x].tile);
mapArray[x].tile.visible = true;
}
The problem is that all the "objects" in the array recive the same x and y coords. So what i suspect is that every single object in the array referes to each other.
What I'm trying to do is create a 20x10 map of tiles. And I need to be able to refer to each tile as a single object.
Shout out if I'm not making sense.
If you create all the tiles like this :
var gfx = new ...
for (...) {
mapArray[x].tile = new tile(gfx);
}
Then all of them share the same gfx object.
You should change your initialization like this :
for (...) {
var gfx = new ...
mapArray[x].tile = new tile(gfx);
}