I’m trying to get as many coordinates as possible for the surface parts of a 3D model that are within the camera’s view range when viewed from multiple viewpoints, and draw their locations.
My idea is to use raycaster.setFromCamera(twoDTarget, eachCamera)
and gradually change the value of twoDTarget from (-1,-1) to (1,1) and assign the coordinates of each viewpoint to the value of eachCamera.
However, raycaster.intersect(model)
returned strance locations like the below image.
Although this may be hard to see on the image, every intersect is in a rotated place.
Perhaps this is the problem derived from the gap between local- and world-coordinate, but I couldn’t find a solution after a trial and error.
Where should be fixed?
Here is the code:
<html>
<head>
<meta charset="utf-8" />
<script src="https://unpkg.com/three@0.140.2/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.137.4/examples/js/controls/OrbitControls.js"></script>
<script src="https://unpkg.com/three@0.137.4/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sprintf/1.1.2/sprintf.min.js"></script>
<script src="js/utils/BufferGeometryUtils.js"></script>
</head>
<body>
<canvas id="myCanvas"></canvas>
<div>
<input type="button" value="Check" id="check">
</div>
<script>
function buttonClick(){
init();
}
function init() {
const width = 960;
const height = 540;
const canvasElement = document.querySelector('#myCanvas');
const renderer = new THREE.WebGLRenderer({
canvas: canvasElement
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
renderer.toneMapping = THREE.CineonToneMapping;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 10000);
camera.position.set(1, 1, 1);
var axes = new THREE.AxisHelper(25);
scene.add(axes);
const controls = new THREE.OrbitControls(camera, canvasElement);
controls.target.set(0, 0, 0);
controls.update();
const directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(-1, -1, -1);
scene.add(directionalLight);
const ambientLight = new THREE.AmbientLight(0xffffff, 10);
scene.add(ambientLight);
const ISMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000});
ISMaterial.opacity = 0.15;
ISMaterial.transparent = true;
let originAndTargetArray = [[3,3,3,0,0,0],[-3,3,3,0,0,0],[3,-3,3,0,0,0],[-3,-3,3,0,0,0],[3,3,-3,0,0,0],[-3,3,-3,0,0,0],[3,-3,-3,0,0,0],[-3,-3,-3,0,0,0]]
const headMaterial = new THREE.MeshLambertMaterial({ color: 0xffff03});
headMaterial.opacity = 0.15;
headMaterial.transparent = true;
for (let i=0; i<originAndTargetArray.length; i++){
const head = new THREE.Mesh(
new THREE.SphereGeometry(0.5, 32, 32),
headMaterial
);
head.position.set(originAndTargetArray[i][0], originAndTargetArray[i][1], originAndTargetArray[i][2]);
scene.add(head);
}
let raycasterList = [];
for (let iO=0;iO<originAndTargetArray.length;iO++){
for (let i=0;i<height;i++){
if (i % 50 != 0) {
continue;
}
for (let j=0;j<height;j++){
if (j % 50 != 0) {
continue;
}
const eachCamera = new THREE.PerspectiveCamera(45, width / height, 0.1, 10000);
eachCamera.position.set(originAndTargetArray[iO][0], originAndTargetArray[iO][1], originAndTargetArray[iO][2]);
const eachControls = new THREE.OrbitControls(eachCamera, canvasElement);
eachControls.target.set(0, 0, 0);
eachControls.update();
const raycaster = new THREE.Raycaster();
const twoDTarget = new THREE.Vector2();
twoDTarget.x = (i / width) * 2 - 1;
twoDTarget.y = (j / height) * 2 - 1;
raycaster.setFromCamera(twoDTarget, eachCamera);
console.log("rc",raycaster);
raycasterList.push(raycaster);
}
}
}
const loader = new THREE.GLTFLoader();
loader.load('./models/gltf/head/scene.gltf', (gltf) => {
model = gltf.scene;
scene.add(model);
const intersectSpheres = [];
for (let i=0; i<raycasterList.length;i++){
console.log()
const intersects = raycasterList[i].intersectObject(model);
if (intersects.length < 1){
continue;
}
intersectXyz = intersects[0].point;
console.log(intersectXyz)
const geometrySphereIS = new THREE.SphereGeometry(0.3, 10, 10);
const geometryTranslatedIS = geometrySphereIS.translate(
intersectXyz.x, intersectXyz.y, intersectXyz.z
);
intersectSpheres.push(geometryTranslatedIS);
}
const geometryIS = THREE.BufferGeometryUtils.mergeBufferGeometries(intersectSpheres);
const meshIS = new THREE.Mesh(geometryIS, ISMaterial);
scene.add(meshIS);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
});
}
const CheckBtn = document.getElementById('CheckBtn');
let checkButton = document.getElementById('check');
checkButton.addEventListener('click', buttonClick);
</script>
</body>
</html>
This GLTF can be downloaded here: