I’m rendering a scene with a custom model in a .glb file type. When I move the camera to the model’s faces I get a consistent parallel projection view. However, if I view the model at an angle then I see top and bottom lines of the model are no longer parallel and moving away from each other. I tested with just a simple Cube Geometry and saw the same effect, which leads me to believe I’m using the controls and camera together incorrectly - I’m just not sure how.
Any help is appreciated! Screenshots and code below.
Versions
three: 0.168.0
node: 18.20.3
Screenshots
Code
export const TestOrthographicCamera = () => {
let canvasRef;
onMount(() => {
// Sizes
const sizes = {
width: 800,
height: 600,
};
// Scene setup
const scene = new THREE.Scene();
// Lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight1.position.set(5, 5, 5);
scene.add(directionalLight1);
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight2.position.set(-5, -5, 5);
scene.add(directionalLight2);
// Model Container
const modelContainer = new THREE.Group();
scene.add(modelContainer);
// Model Loader
const loader = new GLTFLoader();
loader.load(
'/src/annotations/test2.glb',
(gltf) => {
modelContainer.add(gltf.scene);
gltf.scene.scale.set(1, 1, 1);
gltf.scene.traverse((child) => {
if (child.isMesh) {
child.material = new THREE.MeshStandardMaterial({
color: child.material.color,
map: child.material.map,
normalMap: child.material.normalMap,
});
child.castShadow = true;
child.receiveShadow = true;
}
});
const box = new THREE.Box3().setFromObject(modelContainer);
const center = box.getCenter(new THREE.Vector3());
modelContainer.position.sub(center);
const boxHelper = new THREE.BoxHelper(modelContainer, 0xffff00);
scene.add(boxHelper);
},
(progress) => {
console.log('progress');
console.log(progress);
},
(error) => {
console.log('error');
console.log(error);
},
);
// Orthographic Camera
const aspectRatio = sizes.width / sizes.height;
const camera = new THREE.OrthographicCamera(
-1 * aspectRatio,
1 * aspectRatio,
1,
-1,
0.1,
100,
);
camera.position.set(0, 0, 50);
camera.lookAt(0, 0, 0);
scene.add(camera);
// Controls
const controls = new OrbitControls(camera, canvasRef);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.mouseButtons = {
MIDDLE: THREE.MOUSE.ROTATE,
RIGHT: THREE.MOUSE.PAN,
};
controls.enableRotate = true;
controls.enablePan = true;
controls.enableZoom = true;
// Renderer
const renderer = new THREE.WebGLRenderer({
alpha: true,
canvas: canvasRef,
});
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0xffffff, 1);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 3.0;
// Debugging
const cameraHelper = new THREE.CameraHelper(camera);
scene.add(cameraHelper);
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// Animate
const tick = () => {
renderer.render(scene, camera);
window.requestAnimationFrame(tick);
};
tick();
// Cleanup
onCleanup(() => {
renderer.dispose();
});
});
return (
<div>
<h1>Scene</h1>
<canvas ref={canvasRef} class="webgl" />
</div>
);
};