How can I move my camera sideways in ThreeJS - blender

I want to move my camera sideways using the arrow keys. For this I can use something like this to move forward:
const facingDir = this.camera.getWorldDirection(new THREE.Vector3())
this.camera.position.addScaledVector(facingDir, 1)
How do I calculate the vector to go sideways?

I got it working like this:
import * as THREE from 'three'
export default function calcOrthogonalVector(object: THREE.Object3D): THREE.Vector3 {
// create default plane using normal vector
const normalVector = new THREE.Vector3(0, 1, 0)
const normalPlane = new THREE.Plane(normalVector, 0)
// copy rotation of camera to plane
normalPlane.normal.set(0, 1, 0).applyQuaternion(object.quaternion.clone())
// get new normal vector
const newNormalVector = normalPlane.normal
// create new vector from cross product
const crossVector = new THREE.Vector3()
crossVector.crossVectors(newNormalVector, object.getWorldDirection(new THREE.Vector3()))
return crossVector
}

Related

[mxGraph]Changing the preview style of the cell dragged from the toolbar as to center my cursor on the preview, but the guild line doesn't fit along

By default, the cursor is at the left-top of the preview cell .
I've changed the relative position of the preview using transform: translate(-50%, -50%),so the cursor can be at the center on the preview while dragging.
But then I find the guide line doesn't fit along with the changed preview, it's still works according to the original position of the preview.
I've tried some 'offset' API on the docs but still can't work it out.
In this pic, I draw the red box, which is the original position of the preview, and the guide line works wrong
functions concerning the question are on below
const draggingPreview = () => {
const elt = document.createElement("div");
elt.style.width = '60px';
elt.style.height = '60px';
elt.style.transform = "translate(-50%,-50%)";
return elt;
};
const dropHandler = (graph, evt, dropCell, x, y) => {
const parent = graph.getDefaultParent();
this.graph.getModel().beginUpdate();
try {
let vertex = this.graph.insertVertex(
parent,
null,
null,
x - 30,
y - 30,
width,
height,
style
);
vertex.value = "xxxx";
} finally {
this.graph.getModel().endUpdate();
}
};
const ds = mxUtils.makeDraggable(
dom,
graph,
dropHandler,
draggingPreview(),
0,
0,
true,
true
);
ds.setGuidesEnabled(true);

Forge Data Visualization not working on Revit rooms [ITA]

I followed the tutorials from the Forge Data Visualization extension documentation: https://forge.autodesk.com/en/docs/dataviz/v1/developers_guide/quickstart/ on a Revit file. I used the generateMasterViews option to translate the model and I can see the Rooms on the viewer, however I have problems coloring the surfaces of the floors: it seems that the ModelStructureInfo has no rooms.
The result of the ModelStructureInfo on the viewer.model is:
t {model: d, rooms: null}
Here is my code, I added the ITA localized versions of Rooms as 3rd parameter ("Locali"):
const dataVizExtn = await this.viewer.loadExtension("Autodesk.DataVisualization");
// Model Structure Info
let viewerDocument = this.viewer.model.getDocumentNode().getDocument();
const aecModelData = await viewerDocument.downloadAecModelData();
let levelsExt;
if (aecModelData) {
levelsExt = await viewer.loadExtension("Autodesk.AEC.LevelsExtension", {
doNotCreateUI: true
});
}
// get FloorInfo
const floorData = levelsExt.floorSelector.floorData;
const floor = floorData[2];
levelsExt.floorSelector.selectFloor(floor.index, true);
const model = this.viewer.model;
const structureInfo = new Autodesk.DataVisualization.Core.ModelStructureInfo(model);
let levelRoomsMap = await structureInfo.getLevelRoomsMap();
let rooms = levelRoomsMap.getRoomsOnLevel("2 - P2", false);
// Generates `SurfaceShadingData` after assigning each device to a room (Rooms--> Locali).
const shadingData = await structureInfo.generateSurfaceShadingData(devices, undefined, "Locali");
// Use the resulting shading data to generate heatmap from.
await dataVizExtn.setupSurfaceShading(model, shadingData, {
type: "PlanarHeatmap",
placePosition: "min",
usingSlicing: true,
});
// Register a few color stops for sensor values in range [0.0, 1.0]
const sensorType = "Temperature";
const sensorColors = [0x0000ff, 0x00ff00, 0xffff00, 0xff0000];
dataVizExtn.registerSurfaceShadingColors(sensorType, sensorColors);
// Function that provides a [0,1] value for the planar heatmap
function getSensorValue(surfaceShadingPoint, sensorType, pointData) {
const { x, y } = pointData;
const sensorValue = computeSensorValue(x, y);
return clamp(sensorValue, 0.0, 1.0);
}
const sensorType = "Temperature";
dataVizExtn.renderSurfaceShading(floor.name, sensorType, getSensorValue);
How can I solve this issue? Is there something else to do when using a different localization?
Here is a snapshot of what I get from the console:
Which viewer version you're using? There was an issue causing ModelStructureInfo cannot produce the correct LevelRoomsMap, but it gets fixed now. Please use v7.43.0 and try again. Here is the snapshot of my test:
BTW, if you see t {model: d, rooms: null} while constructing the ModelStructureInfo, it's alright, since the room data will be produced after you called ModelStructureInfo#getLevelRoomsMap or ModelStructureInfo#getRoomList.

stats.js shows FPS 0~2, render movement too slow

i'm beginner for three.js also using it for BIM project,
when i load a gltf file of ~25mb i can barely move the whole object and stats.js monitor shows fps of 0~2 at max
gltf file : https://github.com/xeolabs/xeogl/tree/master/examples/models/gltf/schependomlaan
im using THREE js with vuejs
//package.json
"stats.js": "^0.17.0",
"three": "^0.109.0",
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
this.scene = new THREE.Scene();
this.stats = new Stats();
this.stats.showPanel( 0, 1, 2 ); // 0: fps, 1: ms, 2: mb, 3+: custom
let div = document.createElement('div')
div.appendChild(this.stats.dom)
div.style.position = 'absolute';
div.style.top = 0;
div.style.left = 0;
document.getElementsByClassName('gltfViewer')[0].appendChild( div );
// Camera
this.camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1500 );
this.camera.position.set( this.pos, this.pos, this.pos );
// renderer
this.raycaster = new THREE.Raycaster();
this.renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('gltfViewerCanvas'), alpha: false });
this.renderer.setClearColor( 0xefefef );
this.renderer.setPixelRatio( window.devicePixelRatio );
this.renderer.setSize(window.innerWidth, window.innerHeight);
// adding controls
this.controls = new OrbitControls( this.camera, this.renderer.domElement );
this.controls.dampingFactor = 0.1;
this.controls.rotateSpeed = 0.12;
this.controls.enableDamping = true;
this.controls.update();
window.addEventListener('resize', _ => this.render());
this.controls.addEventListener('change', _ => this.render());
// light
var ambientLight = new THREE.AmbientLight( 0xcccccc );
this.scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 0, 1, 1 ).normalize();
this.scene.add( directionalLight );
// loading gltf file
// Instantiate a loader
this.gltfLoader = new GLTFLoader();
// Optional: Provide a DRACOLoader instance to decode compressed mesh data
this.dracoLoader = new DRACOLoader();
this.dracoLoader.setDecoderPath( 'three/examples/js/libs/draco' );
this.gltfLoader.setDRACOLoader( this.dracoLoader );
// Load a glTF resource
this.gltfLoader.load( this.src, this.onGLTFLoaded, this.onGLTFLoading, this.onGLTFLoadingError );
//onGLTFLoaded()
this.scene.add( optimizedGltf.scene );
// gltf.scene.getObjectById(404).visible = false;
this.listGltfObjects(gltf);
this.render();
// render ()
this.renderer.render( this.scene, this.camera );
this.stats.update();
// on mounted component :
animate()
// animate()
this.stats.begin()
this.render();
this.stats.end();
even after applying Draco compression using https://github.com/AnalyticalGraphicsInc/gltf-pipeline nothing changes.
Thanks
On filesize —
Draco compression reduces network size, but not the final amount of uncompressed data that must be sent to your GPU and rendered. If your original mesh was 100mb and you compress it to 25mb, you will still get the framerate of the original 100mb mesh. Aside: Using the -b option of glTF-Pipeline will reduce the size by another 50%, to 13MB, but again doesn't affect FPS.
On framerate —
This model contains 4280 meshes1, each requiring a GPU draw call. That is the source of your low QPS, and unfortunately it's a common problem in BIM models. You'll need to merge these meshes (in a program like Blender, or after loading in three.js) to as few as possible. A model like this should require < 100 draw calls, or even as few as 1.
1 To see this, try opening the model on https://gltf-viewer.donmccurdy.com/ and opening the JavaScript console. You should see a printout of the scene graph, which will contain many different meshes.

PathGraphics not working in real-time or runtime generated

Have simple app using Cesium. I have basic entity with ellipse graphics, moving around, and I need to display its path, using PathGraphics, but it doesn't seem to work for me.
Here's code sample.
const position = new SampledPositionProperty();
const start = [16.096912, 40.4100289];
const startTime = JulianDate.now();
position.addSample(startTime, Cartesian3.fromDegrees(...start));
const diff = 0.0002;
const [x, y] = start;
for (let i = 0; i < 10; i += 1) {
const d = JulianDate.addSeconds(startTime, i + 1, new JulianDate());
const newPos = [x + diff * (i + 1), y + diff * (i + 1)];
position.addSample(d, Cartesian3.fromDegrees(...newPos));
}
app.entities.add({
ellipse: {
semiMinorAxis: 10,
semiMajorAxis: 10,
material: Color.RED,
},
path: {
resolution: 1,
width: 5,
material: Color.YELLOW,
},
position,
});
But when I launch it all I see is moving ellipse, but no path is drawn. Everywhere I searched they say you just have to have position as SampledProperty and it will work, but it doesn't seem to work for me.
In this case, as you can see, I generate data beforehand, but I also tried adding it in runtime - same result. The only working examples i was able to find where using czml - but it doesn't fit my needs - it will be real-time app.
I found the solution by digging through Cesium Sandcastle - you have to set availability property to entity with time range you want path to be shown. Would be cool if it was covered in documentation at least in some way.

three.js Unproject camera within group

I have a camera as child within a Group object and I need to get the origin/direction:
var cameraRig = new THREE.Group();
cameraRig.add( cameraPerspective );
cameraRig.add( cameraOrtho );
scene.add( cameraRig );
function relativeMousePosition () {
var canvasBoundingBox = renderer.domElement.getBoundingClientRect();
var mouse3D = new THREE.Vector3(0, 0, 0.5);
mouse3D.x = ((mouseX - 0) / canvasBoundingBox.width) * 2 - 1;
mouse3D.y = -((mouseY - 0) / canvasBoundingBox.height) * 2 + 1;
return mouse3D;
}
cameraRig.position.set(89,34,91);
cameraRig.lookAt(something.position);
cameraPerspective.position.set(123,345,123);
var dir = relativeMousePosition().unproject(camera).sub(cameraPerspective.position).normalize();
var origin = cameraPerspective.position;
The above code gives a origin + direction with the context of the cameraRig. When I exclude the camera out, having the scene as direct parent, it gives me the world origin/direction which I want. So how to incorporate the cameraRig to get world origin/direction, so I can do picking or whatever?
FIDDLE: https://jsfiddle.net/647qzhab/1/
UPDATE:
As mentioned in the comment by Falk:
var dir = relativeMousePosition().unproject(camera).sub(cameraPerspective.getWorldPosition()).normalize();
var origin = cameraPerspective.getWorldPosition();
The result is better, but not yet fully satisfiing, as the camera rotation seems not applied yet.
I need to update matrixWorld for the cameraRig:
cameraRig.position.set(89,34,91);
cameraRig.lookAt(something.position);
cameraPerspective.position.set(123,345,123);
cameraRig.updateMatrixWorld(true);
cameraPerspective.updateMatrixWorld(true);