Skip to content

Commit

Permalink
Add perspective camera (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
superstar54 authored Jul 9, 2024
1 parent e36ec70 commit 833170c
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 27 deletions.
6 changes: 4 additions & 2 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ async function updateAtoms(filename, fileContent = null) {
editor.avr.atoms = atomsList;
// editor.avr.bondManager.settings[1].color1 = "blue";
// editor.avr.VFManager.addSetting({ origins: "positions", vectors: "movement", color: "#ff0000", radius: 0.1 });
editor.avr.colorType = "CPK";
editor.avr.modelStyle = 1;
editor.instancedMeshPrimitive.fromSettings([]); // Clear mesh primitives
break;
Expand Down Expand Up @@ -158,7 +159,7 @@ async function updateAtoms(filename, fileContent = null) {
nframes: 50,
kpoint: kpoint,
// repeat: [1, 1, 1],
repeat: [4, 4, 1],
repeat: [5, 5, 1],
});

// control the speed of the animation
Expand All @@ -169,8 +170,9 @@ async function updateAtoms(filename, fileContent = null) {
];
editor.avr.frameDuration = 50;
editor.avr.VFManager.addSetting({ origins: "positions", vectors: "movement", color: "#ff0000", radius: 0.1 });
editor.avr.modelStyle = 1;
editor.avr.bondManager.hideLongBonds = false;
editor.avr.showBondedAtoms = false;
editor.avr.modelStyle = 1;
editor.avr.drawModels();
break;
case "Primitives":
Expand Down
2 changes: 1 addition & 1 deletion src/atoms/plugins/vectorField.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export class VectorField {
if atomIndex is null, update all bonds
if atoms is null, use this.viewer.atoms, otherwise use the provided atoms to update the bonds, e.g. trajectory data
*/
// console.log("updateBondMesh: ", atomIndex);
// console.log("updateArrowMesh: ", atomIndex);
if (atoms === null) {
atoms = this.viewer.atoms;
}
Expand Down
3 changes: 1 addition & 2 deletions src/core/GUIManager.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as THREE from "three";
import { GUI } from "dat.gui";
import { setupCameraGUI } from "../tools/camera.js"; // Assuming these are utility functions
import { createViewpointButtons } from "../tools/viewpoint.js";
Expand Down Expand Up @@ -49,7 +48,7 @@ class GUIManager {

addCameraControls() {
createViewpointButtons(this.weas, this.gui);
setupCameraGUI(this.gui, this.weas.tjs.camera, this.weas.tjs.scene);
setupCameraGUI(this.weas.tjs, this.gui, this.weas.tjs.camera);
}

addButtons() {
Expand Down
37 changes: 31 additions & 6 deletions src/core/blendjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,27 @@ export class BlendJS {
this.meshes = {};
this.lights = {};
this.renderers = {}; // New property to store renderers
this._cameraType = "Orthographic"; //"Perspective"
this.init();
}

get cameraType() {
return this._cameraType;
}

set cameraType(value) {
this._cameraType = value;
this.controls = new OrbitControls(this.camera, this.renderers["MainRenderer"].renderer.domElement);
this.updateCameraAndControls({});
}

get camera() {
if (this._cameraType === "Orthographic") {
return this.orthographicCamera;
}
return this.perspectiveCamera;
}

init() {
this.scene.background = new THREE.Color(0xffffff); // Set the scene's background to white
// Create a renderer
Expand All @@ -70,13 +89,14 @@ export class BlendJS {
labelRenderer.domElement.style.pointerEvents = "none";
this.addRenderer("LabelRenderer", labelRenderer);
// Create a camera
// this.camera = new THREE.PerspectiveCamera(50, this.containerElement.clientWidth / this.containerElement.clientHeight, 1, 500);
this.perspectiveCamera = new THREE.PerspectiveCamera(50, this.containerElement.clientWidth / this.containerElement.clientHeight, 1, 500);
this.perspectiveCamera.layers.enable(1);
const frustumSize = 20; // This can be adjusted based on scene's scale
const aspect = this.containerElement.clientWidth / this.containerElement.clientHeight;
const frustumHalfHeight = frustumSize / 2;
const frustumHalfWidth = frustumHalfHeight * aspect;

this.camera = new OrthographicCamera(
this.orthographicCamera = new OrthographicCamera(
-frustumHalfWidth, // left
frustumHalfWidth, // right
frustumHalfHeight, // top
Expand All @@ -85,12 +105,13 @@ export class BlendJS {
2000, // far clipping plane
this,
);
this.orthographicCamera.layers.enable(1);
// Set initial camera position
this.camera.position.set(0, -100, 0);
this.camera.lookAt(0, 0, 0);
// Enable layer 1 for the camera
// this layer will be used for vertex indicators
this.camera.layers.enable(1);

this.scene.add(this.camera);
// Create a light
const light = new THREE.DirectionalLight(0xffffff, 2.0);
Expand Down Expand Up @@ -174,7 +195,7 @@ export class BlendJS {
this.render();
}
//
updateCameraAndControls({ lookAt = null, direction = [0, 0, 1], distance = null, zoom = 1 }) {
updateCameraAndControls({ lookAt = null, direction = [0, 0, 1], distance = null, zoom = 1, fov = 50 }) {
/*
Calculate the camera parameters based on the bounding box of the scene and the camera direction
The camera to look at the lookAt, and rotate around the lookAt of the atoms.
Expand Down Expand Up @@ -215,10 +236,14 @@ export class BlendJS {
distance = size.z + padding;
}
let cameraPosition = lookAt.clone().add(direction.multiplyScalar(distance));
this.camera.updatePosition(cameraPosition.x, cameraPosition.y, cameraPosition.z);
this.camera.position.set(cameraPosition.x, cameraPosition.y, cameraPosition.z);

this.camera.lookAt(lookAt);
this.camera.updateZoom(zoom);
if (this.camera.isOrthographicCamera) {
this.camera.updateZoom(zoom);
} else {
this.camera.fov = fov; // Set the new field of view
}
this.camera.updateProjectionMatrix();
// Set the camera target to the lookAt of the atoms
this.controls.target.set(lookAt.x, lookAt.y, lookAt.z);
Expand Down
51 changes: 35 additions & 16 deletions src/tools/camera.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,51 @@
export function setupCameraGUI(gui, camera) {
import * as THREE from "three";

export function setupCameraGUI(tjs, gui, camera) {
// Create a folder for camera parameters
const cameraFolder = gui.addFolder("Camera");

// Temp storage for position to use in onChange callbacks
const position = { x: camera.position.x, y: camera.position.y, z: camera.position.z };

// Dropdown for selecting camera type
const cameraType = { type: camera instanceof THREE.PerspectiveCamera ? "Perspective" : "Orthographic" };
cameraFolder
.add(cameraType, "type", ["Perspective", "Orthographic"])
.name("Camera Type")
.onChange((newType) => {
tjs.cameraType = newType;
tjs.updateCameraAndControls({});
});

function updateCameraPosition(x, y, z) {
camera.position.set(x, y, z);
position.x = x;
position.y = y;
position.z = z;
}

// Add GUI controllers for position
cameraFolder
.add(position, "x", -100, 100)
.name("X Position")
.onChange((newValue) => {
camera.updatePosition(newValue, position.y, position.z);
// Update the temp storage to ensure consistency
position.x = newValue;
});
.onChange((newValue) => updateCameraPosition(newValue, position.y, position.z));
cameraFolder
.add(position, "y", -100, 100)
.name("Y Position")
.onChange((newValue) => {
camera.updatePosition(position.x, newValue, position.z);
// Update the temp storage to ensure consistency
position.y = newValue;
});
.onChange((newValue) => updateCameraPosition(position.x, newValue, position.z));
cameraFolder
.add(position, "z", -100, 100)
.name("Z Position")
.onChange((newValue) => {
camera.updatePosition(position.x, position.y, newValue);
// Update the temp storage to ensure consistency
position.z = newValue;
});
.onChange((newValue) => updateCameraPosition(position.x, position.y, newValue));

function updateCameraType(type) {
if (type === "Perspective") {
camera.fov = camera.fov || 50; // Default fov if not set
camera.updateProjectionMatrix();
} else if (type === "Orthographic") {
// Specific adjustments for Orthographic camera can be made here
// camera.left, camera.right, camera.top, camera.bottom, etc.
camera.updateProjectionMatrix();
}
}
}
9 changes: 9 additions & 0 deletions tests/e2e/gui.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ test("Gui config", async ({ page }) => {
await expect(page).toHaveScreenshot();
});

test("Camera", async ({ page }) => {
await page.goto("http://127.0.0.1:8080/tests/e2e/testCrystal.html");
// open gui
await page.evaluate(() => {
window.editor.tjs.cameraType = "perspective";
});
await expect(page).toHaveScreenshot("Camera-perspective.png");
});

test("Crystal", async ({ page }) => {
await page.goto("http://127.0.0.1:8080/tests/e2e/testCrystal.html");
await expect(page).toHaveScreenshot();
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 833170c

Please sign in to comment.