mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-12-28 13:53:49 +01:00
380 lines
8.7 KiB
HTML
Executable File
380 lines
8.7 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>three.js webgl - vector - text</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 {
|
|
font-family: Monospace;
|
|
background-color: #f0f0f0;
|
|
margin: 0px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
#info {
|
|
position: absolute;
|
|
top: 10px;
|
|
width: 100%;
|
|
text-align: center;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="info">
|
|
<a href="http://threejs.org" target="_blank">three.js</a> webgl - Resolution-Independent Vector Fonts. <a href="https://github.com/mrdoob/three.js/issues/4746">info</a>.
|
|
</div>
|
|
<script src="../build/three.min.js"></script>
|
|
<script src="./js/controls/OrbitControls.js"></script>
|
|
|
|
<script src="js/libs/stats.min.js"></script>
|
|
|
|
<!-- load the font file from canvas-text -->
|
|
|
|
<script src="fonts/helvetiker_regular.typeface.js"></script>
|
|
|
|
<script type="x-shader/x-fragment" id="fs">
|
|
|
|
varying vec2 vUv;
|
|
varying float flip;
|
|
uniform vec3 color;
|
|
|
|
float inCurve(vec2 uv) {
|
|
return uv.x * uv.x - uv.y;
|
|
}
|
|
|
|
float delta = 0.1;
|
|
|
|
void main() {
|
|
float x = inCurve(vUv);
|
|
|
|
if (x * flip > 0.) discard;
|
|
gl_FragColor = vec4(color, 1.);
|
|
}
|
|
|
|
</script>
|
|
|
|
<script type="x-shader/x-vertex" id="vs">
|
|
|
|
varying vec2 vUv;
|
|
attribute float invert;
|
|
varying float flip;
|
|
|
|
void main() {
|
|
|
|
vUv = uv;
|
|
flip = invert;
|
|
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
gl_Position = projectionMatrix * mvPosition;
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
<script>
|
|
|
|
var stats;
|
|
|
|
var camera, scene, renderer, controls;
|
|
|
|
var group, text;
|
|
|
|
var t = false;
|
|
|
|
function toggle() {
|
|
|
|
if ( t ) {
|
|
|
|
text2.visible = 0;
|
|
text1.visible = 1;
|
|
|
|
} else {
|
|
|
|
text2.visible = 1;
|
|
text1.visible = 0;
|
|
|
|
}
|
|
|
|
t = !t;
|
|
}
|
|
|
|
init();
|
|
animate();
|
|
|
|
function init() {
|
|
|
|
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
|
|
camera.position.set( 0, 100, 500 );
|
|
|
|
controls = new THREE.OrbitControls( camera );
|
|
controls.center.set( 0, 100, 0 );
|
|
|
|
scene = new THREE.Scene();
|
|
|
|
var theText = "&"; // i % & j b 8
|
|
|
|
var options = {
|
|
size: 180,
|
|
height: 20,
|
|
curveSegments: 2,
|
|
font: "helvetiker",
|
|
bevelEnabled: false
|
|
};
|
|
|
|
group = new THREE.Group();
|
|
scene.add( group );
|
|
|
|
|
|
var textMaterial = new THREE.MeshBasicMaterial( { color: new THREE.Color(0, 0, 1 ), overdraw: 0.5, wireframe: true, side: THREE.DoubleSide } );
|
|
|
|
textShapes = THREE.FontUtils.generateShapes( theText, options );
|
|
|
|
text3d = new THREE.ShapeGeometry( textShapes );
|
|
|
|
text3d.computeBoundingBox();
|
|
var centerOffset = -0.5 * ( text3d.boundingBox.max.x - text3d.boundingBox.min.x );
|
|
text = new THREE.Mesh( text3d, textMaterial );
|
|
|
|
text.position.x = centerOffset - 150;
|
|
group.add( text );
|
|
|
|
//
|
|
|
|
vA = new THREE.Vector2();
|
|
vB = new THREE.Vector2();
|
|
vDot = new THREE.Vector2();
|
|
|
|
function processShape(path, reverse) {
|
|
|
|
var pts = []; // bigger area (convex hull)
|
|
var pts2 = []; // smaller area (full solid shapes)
|
|
var beziers = []; // quad bezier points
|
|
var invert = [];
|
|
var z;
|
|
|
|
var wind;
|
|
|
|
pts.push( path[0].getPoint(0) );
|
|
pts2.push( path[0].getPoint(0) );
|
|
|
|
for (var i=0; i < path.length; i++) {
|
|
curve = path[i];
|
|
if (curve instanceof THREE.LineCurve) {
|
|
pts.push( curve.v2 );
|
|
pts2.push( curve.v2 );
|
|
} else if (curve instanceof THREE.QuadraticBezierCurve) {
|
|
vA = vA.subVectors( curve.v1, curve.v0 ); // .normalize()
|
|
vB = vB.subVectors( curve.v2, curve.v1 );
|
|
z = vA.x * vB.y - vA.y * vB.x; // z component of cross Production
|
|
wind = z < 0; // clockwise/anticlock wind
|
|
// if (reverse) wind = !wind;
|
|
|
|
// console.log(z, wind , wind ? 'clockwise' : 'anti');
|
|
|
|
if (wind) {
|
|
pts.push( curve.v1 );
|
|
pts.push( curve.v2 );
|
|
pts2.push( curve.v2 );
|
|
} else {
|
|
pts.push( curve.v2 );
|
|
pts2.push( curve.v1 );
|
|
pts2.push( curve.v2 );
|
|
}
|
|
|
|
var flip = wind ? 1 : -1;
|
|
// if (reverse) flip *= -1;
|
|
|
|
invert.push(flip, flip, flip);
|
|
beziers.push( curve.v0, curve.v1, curve.v2);
|
|
|
|
}
|
|
}
|
|
|
|
return {
|
|
pts: pts,
|
|
pts2: pts2,
|
|
beziers: beziers,
|
|
invert: invert
|
|
};
|
|
}
|
|
|
|
var subshape;
|
|
var convexhullShapeGroup = [];
|
|
var solidShapeGroup = [];
|
|
|
|
var beziers = [], invert = [];
|
|
|
|
for (var s=0;s<textShapes.length;s++) {
|
|
|
|
subshape = textShapes[s];
|
|
var process = processShape(subshape.curves);
|
|
|
|
pts = process.pts;
|
|
pts2 = process.pts2;
|
|
beziers = beziers.concat(process.beziers);
|
|
invert = invert.concat(process.invert);
|
|
|
|
convexhullShape = new THREE.Shape( pts );
|
|
solidShape = new THREE.Shape( pts2 );
|
|
|
|
convexhullShapeGroup.push( convexhullShape );
|
|
solidShapeGroup.push( solidShape );
|
|
|
|
for (var i=0; i<subshape.holes.length;i++) {
|
|
hole = subshape.holes[i];
|
|
// console.log('hole', hole);
|
|
|
|
process = processShape(hole.curves, true);
|
|
|
|
pts = process.pts;
|
|
pts2 = process.pts2;
|
|
beziers = beziers.concat(process.beziers);
|
|
invert = invert.concat(process.invert);
|
|
|
|
convexhullShape.holes.push(new THREE.Shape(pts));
|
|
solidShape.holes.push(new THREE.Shape(pts2));
|
|
|
|
}
|
|
|
|
} // end of subshape
|
|
|
|
bezierGeometry = new THREE.Geometry();
|
|
|
|
for (var i=0;i<beziers.length;i++) {
|
|
p = beziers[i];
|
|
bezierGeometry.vertices.push( new THREE.Vector3(p.x, p.y, 0) );
|
|
}
|
|
|
|
for (i=0;i<beziers.length;i+=3) {
|
|
bezierGeometry.faces.push( new THREE.Face3(i, i+1, i+2) );
|
|
bezierGeometry.faceVertexUvs[0].push( [
|
|
new THREE.Vector2(0, 0),
|
|
new THREE.Vector2(0.5, 0),
|
|
new THREE.Vector2(1, 1)
|
|
] );
|
|
}
|
|
|
|
text3d = new THREE.ShapeGeometry( convexhullShapeGroup );
|
|
text3d.computeBoundingBox();
|
|
var centerOffset = -0.5 * ( text3d.boundingBox.max.x - text3d.boundingBox.min.x );
|
|
|
|
text1 = new THREE.Mesh( text3d, textMaterial );
|
|
|
|
text1.position.x = centerOffset + 150;
|
|
|
|
group.add( text1 );
|
|
|
|
text3d = new THREE.ShapeGeometry( solidShapeGroup );
|
|
text3d.computeBoundingBox();
|
|
var centerOffset = -0.5 * ( text3d.boundingBox.max.x - text3d.boundingBox.min.x );
|
|
|
|
text2 = new THREE.Mesh( text3d, new THREE.MeshBasicMaterial( { color: new THREE.Color(1, 0, 0 ), side: THREE.DoubleSide, wireframe: true } ) );
|
|
|
|
text2.position.x = centerOffset + 150;
|
|
|
|
group.add( text2 );
|
|
|
|
//
|
|
bezierGeometry.computeBoundingBox();
|
|
bezierGeometry.computeFaceNormals();
|
|
bezierGeometry.computeVertexNormals();
|
|
|
|
//
|
|
|
|
var uniforms = {
|
|
color: { type: 'c', value: new THREE.Color(0.45 * 0xffffff) }
|
|
};
|
|
var vertexShader = document.getElementById( 'vs' ).textContent;
|
|
var fragmentShader = document.getElementById( 'fs' ).textContent;
|
|
|
|
|
|
|
|
newMaterial = new THREE.ShaderMaterial({
|
|
attributes: { invert: { type: 'f', value: invert } },
|
|
uniforms: uniforms,
|
|
vertexShader: vertexShader,
|
|
fragmentShader: fragmentShader,
|
|
side: THREE.DoubleSide
|
|
});
|
|
|
|
|
|
text = new THREE.Mesh( bezierGeometry, newMaterial );
|
|
|
|
text.position.x = centerOffset;
|
|
text.position.y = 0;
|
|
text.position.z = 0;
|
|
|
|
text.rotation.x = 0;
|
|
text.rotation.y = Math.PI * 2;
|
|
|
|
group.add( text );
|
|
|
|
//
|
|
|
|
|
|
text3d = new THREE.ShapeGeometry( solidShapeGroup );
|
|
text3d.computeBoundingBox();
|
|
|
|
text = new THREE.Mesh( text3d, new THREE.MeshBasicMaterial( { color: 0.45 * 0xffffff, side: THREE.DoubleSide } ) );
|
|
text.position.x = centerOffset;
|
|
text.position.y = 0;
|
|
text.position.z = 0;
|
|
|
|
text.rotation.x = 0;
|
|
text.rotation.y = Math.PI * 2;
|
|
|
|
group.add( text );
|
|
|
|
//
|
|
|
|
renderer = new THREE.WebGLRenderer( { antialias: true } );
|
|
renderer.setClearColor( 0xf0f0f0 );
|
|
renderer.setPixelRatio( window.devicePixelRatio );
|
|
renderer.setSize( window.innerWidth, window.innerHeight );
|
|
document.body.appendChild( renderer.domElement );
|
|
|
|
stats = new Stats();
|
|
stats.domElement.style.position = 'absolute';
|
|
stats.domElement.style.top = '0px';
|
|
document.body.appendChild( stats.domElement );
|
|
|
|
document.addEventListener( 'mousedown', toggle, false );
|
|
|
|
window.addEventListener( 'resize', onWindowResize, false );
|
|
|
|
}
|
|
|
|
function onWindowResize() {
|
|
|
|
camera.aspect = window.innerWidth / window.innerHeight;
|
|
camera.updateProjectionMatrix();
|
|
|
|
renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
|
}
|
|
|
|
|
|
//
|
|
|
|
function animate() {
|
|
|
|
requestAnimationFrame( animate );
|
|
|
|
render();
|
|
stats.update();
|
|
|
|
}
|
|
|
|
function render() {
|
|
|
|
controls.update();
|
|
renderer.render( scene, camera );
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|