mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-12-28 13:53:49 +01:00
361 lines
8.6 KiB
HTML
Executable File
361 lines
8.6 KiB
HTML
Executable File
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>three.js webgl - interactive - raycasting - pointcloud</title>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
|
<style>
|
|
body {
|
|
color: #ffffff;
|
|
background-color: #000000;
|
|
margin: 0px;
|
|
overflow: hidden;
|
|
}
|
|
#info {
|
|
position: absolute;
|
|
top: 0px;
|
|
width: 100%;
|
|
padding: 5px;
|
|
font-family: Monospace;
|
|
font-size: 13px;
|
|
text-align: center;
|
|
font-weight: bold;
|
|
}
|
|
a {
|
|
color: #fff;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="container"></div>
|
|
<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> webgl - interactive - raycasting - pointcloud </div>
|
|
|
|
<script src="../build/three.min.js"></script>
|
|
|
|
<script src="js/Detector.js"></script>
|
|
<script src="js/libs/stats.min.js"></script>
|
|
|
|
<script>
|
|
|
|
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
|
|
|
|
var renderer, scene, camera, stats;
|
|
var pointclouds;
|
|
var raycaster, intersects;
|
|
var mouse = new THREE.Vector2();
|
|
var intersection = null;
|
|
var spheres = [];
|
|
var spheresIndex = 0;
|
|
var clock;
|
|
|
|
var threshold = 0.1;
|
|
var pointSize = 0.05;
|
|
var width = 150;
|
|
var length = 150;
|
|
var rotateY = new THREE.Matrix4().makeRotationY( 0.005 );
|
|
|
|
init();
|
|
animate();
|
|
|
|
function generatePointCloudGeometry( color, width, length ){
|
|
|
|
var geometry = new THREE.BufferGeometry();
|
|
var numPoints = width*length;
|
|
|
|
var positions = new Float32Array( numPoints*3 );
|
|
var colors = new Float32Array( numPoints*3 );
|
|
|
|
var k = 0;
|
|
|
|
for( var i = 0; i < width; i++ ) {
|
|
|
|
for( var j = 0; j < length; j++ ) {
|
|
|
|
var u = i / width;
|
|
var v = j / length;
|
|
var x = u - 0.5;
|
|
var y = ( Math.cos( u * Math.PI * 8 ) + Math.sin( v * Math.PI * 8 ) ) / 20;
|
|
var z = v - 0.5;
|
|
|
|
positions[ 3 * k ] = x;
|
|
positions[ 3 * k + 1 ] = y;
|
|
positions[ 3 * k + 2 ] = z;
|
|
|
|
var intensity = ( y + 0.1 ) * 5;
|
|
colors[ 3 * k ] = color.r * intensity;
|
|
colors[ 3 * k + 1 ] = color.g * intensity;
|
|
colors[ 3 * k + 2 ] = color.b * intensity;
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
|
|
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
|
|
geometry.computeBoundingBox();
|
|
|
|
return geometry;
|
|
|
|
}
|
|
|
|
function generatePointcloud( color, width, length ) {
|
|
|
|
var geometry = generatePointCloudGeometry( color, width, length );
|
|
|
|
var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
|
|
var pointcloud = new THREE.PointCloud( geometry, material );
|
|
|
|
return pointcloud;
|
|
|
|
}
|
|
|
|
function generateIndexedPointcloud( color, width, length ) {
|
|
|
|
var geometry = generatePointCloudGeometry( color, width, length );
|
|
var numPoints = width * length;
|
|
var indices = new Uint16Array( numPoints );
|
|
|
|
var k = 0;
|
|
|
|
for( var i = 0; i < width; i++ ) {
|
|
|
|
for( var j = 0; j < length; j++ ) {
|
|
|
|
indices[ k ] = k;
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
|
|
|
|
var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
|
|
var pointcloud = new THREE.PointCloud( geometry, material );
|
|
|
|
return pointcloud;
|
|
|
|
}
|
|
|
|
function generateIndexedWithOffsetPointcloud( color, width, length ){
|
|
|
|
var geometry = generatePointCloudGeometry( color, width, length );
|
|
var numPoints = width * length;
|
|
var indices = new Uint16Array( numPoints );
|
|
|
|
var k = 0;
|
|
|
|
for( var i = 0; i < width; i++ ){
|
|
|
|
for( var j = 0; j < length; j++ ) {
|
|
|
|
indices[ k ] = k;
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
|
|
|
|
var offset = { start: 0, count: indices.length, index: 0 };
|
|
geometry.offsets.push( offset );
|
|
|
|
var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
|
|
var pointcloud = new THREE.PointCloud( geometry, material );
|
|
|
|
return pointcloud;
|
|
|
|
}
|
|
|
|
function generateRegularPointcloud( color, width, length ) {
|
|
|
|
var geometry = new THREE.Geometry();
|
|
var numPoints = width * length;
|
|
|
|
var colors = [];
|
|
|
|
var k = 0;
|
|
|
|
for( var i = 0; i < width; i++ ) {
|
|
|
|
for( var j = 0; j < length; j++ ) {
|
|
|
|
var u = i / width;
|
|
var v = j / length;
|
|
var x = u - 0.5;
|
|
var y = ( Math.cos( u * Math.PI * 8 ) + Math.sin( v * Math.PI * 8) ) / 20;
|
|
var z = v - 0.5;
|
|
var v = new THREE.Vector3( x,y,z );
|
|
|
|
var intensity = ( y + 0.1 ) * 7;
|
|
colors[ 3 * k ] = color.r * intensity;
|
|
colors[ 3 * k + 1 ] = color.g * intensity;
|
|
colors[ 3 * k + 2 ] = color.b * intensity;
|
|
|
|
geometry.vertices.push( v );
|
|
colors[ k ] = ( color.clone().multiplyScalar( intensity ) );
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
geometry.colors = colors;
|
|
geometry.computeBoundingBox();
|
|
|
|
var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
|
|
var pointcloud = new THREE.PointCloud( geometry, material );
|
|
|
|
return pointcloud;
|
|
|
|
}
|
|
|
|
function init() {
|
|
|
|
container = document.getElementById( 'container' );
|
|
|
|
scene = new THREE.Scene();
|
|
|
|
clock = new THREE.Clock();
|
|
|
|
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
|
|
camera.applyMatrix( new THREE.Matrix4().makeTranslation( 0,0,20 ) );
|
|
camera.applyMatrix( new THREE.Matrix4().makeRotationX( -0.5 ) );
|
|
|
|
//
|
|
|
|
pcBuffer = generatePointcloud( new THREE.Color( 1,0,0 ), width, length );
|
|
pcBuffer.scale.set( 10,10,10 );
|
|
pcBuffer.position.set( -5,0,5 );
|
|
scene.add( pcBuffer );
|
|
|
|
var pcIndexed = generateIndexedPointcloud( new THREE.Color( 0,1,0 ), width, length );
|
|
pcIndexed.scale.set( 10,10,10 );
|
|
pcIndexed.position.set( 5,0,5 );
|
|
scene.add( pcIndexed );
|
|
|
|
var pcIndexedOffset = generateIndexedWithOffsetPointcloud( new THREE.Color( 0,1,1 ), width, length );
|
|
pcIndexedOffset.scale.set( 10,10,10 );
|
|
pcIndexedOffset.position.set( 5,0,-5 );
|
|
scene.add( pcIndexedOffset );
|
|
|
|
var pcRegular = generateRegularPointcloud( new THREE.Color( 1,0,1 ), width, length );
|
|
pcRegular.scale.set( 10,10,10 );
|
|
pcRegular.position.set( -5,0,-5 );
|
|
scene.add( pcRegular );
|
|
|
|
pointclouds = [ pcBuffer, pcIndexed, pcIndexedOffset, pcRegular ];
|
|
|
|
//
|
|
|
|
var sphereGeometry = new THREE.SphereGeometry( 0.1, 32, 32 );
|
|
var sphereMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000, shading: THREE.FlatShading } );
|
|
|
|
for ( var i = 0; i < 40; i++ ) {
|
|
|
|
var sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
|
|
scene.add( sphere );
|
|
spheres.push( sphere );
|
|
|
|
}
|
|
|
|
//
|
|
|
|
renderer = new THREE.WebGLRenderer();
|
|
renderer.setPixelRatio( window.devicePixelRatio );
|
|
renderer.setSize( window.innerWidth, window.innerHeight );
|
|
container.appendChild( renderer.domElement );
|
|
|
|
//
|
|
|
|
raycaster = new THREE.Raycaster();
|
|
raycaster.params.PointCloud.threshold = threshold;
|
|
|
|
//
|
|
|
|
stats = new Stats();
|
|
stats.domElement.style.position = 'absolute';
|
|
stats.domElement.style.top = '0px';
|
|
container.appendChild( stats.domElement );
|
|
|
|
//
|
|
|
|
window.addEventListener( 'resize', onWindowResize, false );
|
|
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
|
|
|
|
}
|
|
|
|
function onDocumentMouseMove( event ) {
|
|
|
|
event.preventDefault();
|
|
|
|
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
|
|
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
|
|
|
|
}
|
|
|
|
function onWindowResize() {
|
|
|
|
camera.aspect = window.innerWidth / window.innerHeight;
|
|
camera.updateProjectionMatrix();
|
|
|
|
renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
|
}
|
|
|
|
function animate() {
|
|
|
|
requestAnimationFrame( animate );
|
|
|
|
render();
|
|
stats.update();
|
|
|
|
}
|
|
|
|
var toggle = 0;
|
|
|
|
function render() {
|
|
|
|
camera.applyMatrix( rotateY );
|
|
camera.updateMatrixWorld();
|
|
|
|
raycaster.setFromCamera( mouse, camera );
|
|
|
|
var intersections = raycaster.intersectObjects( pointclouds );
|
|
intersection = ( intersections.length ) > 0 ? intersections[ 0 ] : null;
|
|
|
|
if ( toggle > 0.02 && intersection !== null) {
|
|
|
|
spheres[ spheresIndex ].position.copy( intersection.point );
|
|
spheres[ spheresIndex ].scale.set( 1, 1, 1 );
|
|
spheresIndex = ( spheresIndex + 1 ) % spheres.length;
|
|
|
|
toggle = 0;
|
|
|
|
}
|
|
|
|
for ( var i = 0; i < spheres.length; i++ ) {
|
|
|
|
var sphere = spheres[ i ];
|
|
sphere.scale.multiplyScalar( 0.98 );
|
|
sphere.scale.clampScalar( 0.01, 1 );
|
|
|
|
}
|
|
|
|
toggle += clock.getDelta();
|
|
|
|
renderer.render( scene, camera );
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|