diff --git a/example/web_gl_custom_attributes_lines/web_gl_custom_attributes_lines.dart b/example/web_gl_custom_attributes_lines/web_gl_custom_attributes_lines.dart index 4c389bb9..f48c6146 100644 --- a/example/web_gl_custom_attributes_lines/web_gl_custom_attributes_lines.dart +++ b/example/web_gl_custom_attributes_lines/web_gl_custom_attributes_lines.dart @@ -12,13 +12,13 @@ var uniforms, amplitude, opacity, color; var attributes, displacement, customColor; var text = "three.dart", - height = 15.0, + height = 15, size = 50, curveSegments = 10, steps = 40, - bevelThickness = 5, + bevelThickness = 5.0, bevelSize = 1.5, bevelSegments = 10, bevelEnabled = true, @@ -88,7 +88,6 @@ void init() { curveSegments, 1, null, - null, 0, 1, size, diff --git a/example/web_gl_geometries/UV_Grid_Sm.jpg b/example/web_gl_geometries/UV_Grid_Sm.jpg new file mode 100644 index 00000000..bcc6ee1e Binary files /dev/null and b/example/web_gl_geometries/UV_Grid_Sm.jpg differ diff --git a/example/web_gl_geometries/textures/ash_uvgrid01.jpg b/example/web_gl_geometries/textures/ash_uvgrid01.jpg deleted file mode 100644 index 4459784f..00000000 Binary files a/example/web_gl_geometries/textures/ash_uvgrid01.jpg and /dev/null differ diff --git a/example/web_gl_geometries/web_gl_geometries.dart b/example/web_gl_geometries/web_gl_geometries.dart index 4980f41d..b11fa714 100644 --- a/example/web_gl_geometries/web_gl_geometries.dart +++ b/example/web_gl_geometries/web_gl_geometries.dart @@ -1,16 +1,17 @@ +/* + * Based on r70 + */ + import 'dart:html'; import 'dart:math' as Math; -import 'package:vector_math/vector_math.dart'; import 'package:three/three.dart'; +import 'package:vector_math/vector_math.dart'; import 'package:three/extras/image_utils.dart' as ImageUtils; -import 'package:three/extras/scene_utils.dart' as SceneUtils; - -Element container; +DivElement container; +WebGLRenderer renderer; PerspectiveCamera camera; Scene scene; -WebGLRenderer renderer; - void main() { init(); @@ -18,118 +19,89 @@ void main() { } void init() { + container = new DivElement(); + document.body.append(container); - container = new Element.tag('div'); - document.body.nodes.add(container); - - camera = new PerspectiveCamera(45.0, window.innerWidth / window.innerHeight, 1.0, 2000.00); - camera.position.y = 400.0; - + camera = new PerspectiveCamera(45.0, window.innerWidth / window.innerHeight, 1.0, 2000.0) + ..position.y = 400.0; + scene = new Scene(); - - scene.add(new AmbientLight(0x404040)); - - var light = new DirectionalLight(0xffffff); - light.position.setValues(0.0, 1.0, 0.0); - scene.add(light); - - Texture map = ImageUtils.loadTexture('textures/ash_uvgrid01.jpg'); + + var map = ImageUtils.loadTexture('UV_Grid_Sm.jpg'); map.wrapS = map.wrapT = RepeatWrapping; map.anisotropy = 16; - var materials = [ - new MeshLambertMaterial(ambient: 0xbbbbbb, map: map, side: DoubleSide), - new MeshBasicMaterial(color: 0xffffff, wireframe: true, transparent: true, opacity: 0.1, side: DoubleSide)]; - - var object = SceneUtils.createMultiMaterialObject(new CubeGeometry(100.0, 100.0, 100.0, 4, 4, 4), materials); - object.position.setValues(-200.0, 0.0, 400.0); - scene.add(object); - - - object = SceneUtils.createMultiMaterialObject(new CylinderGeometry(25.0, 75.0, 100.0, 40, 5), materials); - object.position.setValues(0.0, 0.0, 400.0); - scene.add(object); - - object = SceneUtils.createMultiMaterialObject(new IcosahedronGeometry(75.0, 1), materials); - object.position.setValues(-200.0, 0.0, 200.0); - scene.add(object); - - object = SceneUtils.createMultiMaterialObject(new OctahedronGeometry(75.0, 2), materials); - object.position.setValues(0.0, 0.0, 200.0); - scene.add(object); - - - object = SceneUtils.createMultiMaterialObject(new TetrahedronGeometry(75.0, 0), materials); - object.position.setValues(200.0, 0.0, 200.0); - scene.add(object); - - object = SceneUtils.createMultiMaterialObject(new PlaneGeometry(100.0, 100.0, 4, 4), materials); - object.position.setValues(-200.0, 0.0, 0.0); - scene.add(object); - - var object2 = SceneUtils.createMultiMaterialObject(new CircleGeometry(50, 10, 0, Math.PI), materials); - object2.rotation.x = Math.PI / 2; - object.add(object2); - - object = SceneUtils.createMultiMaterialObject(new SphereGeometry(75.0, 20, 10), materials); - object.position.setValues(0.0, 0.0, 0.0); - scene.add(object); - - - var points = []; - - for (var i = 0; i < 50; i++) { - - points.add(new Vector3(Math.sin(i * 0.2) * 15.0 + 50.0, 0.0, (i - 5) * 2.0)); - - } - - object = SceneUtils.createMultiMaterialObject(new LatheGeometry(points, 20), materials); - object.position.setValues(200.0, 0.0, 0.0); - scene.add(object); - - object = SceneUtils.createMultiMaterialObject(new TorusGeometry(50, 20, 20, 20), materials); - object.position.setValues(-200.0, 0.0, -200.0); - scene.add(object); - - object = SceneUtils.createMultiMaterialObject(new TorusKnotGeometry(50.0, 10.0, 50, 20), materials); - object.position.setValues(0.0, 0.0, -200.0); - scene.add(object); - - object = new AxisHelper(); - object.position.setValues(200.0, 0.0, -200.0); - object.scale.x = object.scale.y = object.scale.z = 0.5; - scene.add(object); - - - object = new ArrowHelper(new Vector3(0.0, 1.0, 0.0), new Vector3.zero(), 50.0); - object.position.setValues(200.0, 0.0, 400.0); - scene.add(object); - - renderer = new WebGLRenderer(); // TODO - {antialias: true} - renderer.setSize(window.innerWidth, window.innerHeight); - renderer.sortObjects = false; - - container.nodes.add(renderer.domElement); - + var material = new MeshLambertMaterial(ambient: 0xbbbbbb, map: map, side: DoubleSide); + + scene.add(new Mesh(new SphereGeometry(75.0, 20, 10), material) + ..position.setValues(-400.0, 0.0, 200.0)); + + scene.add(new Mesh(new IcosahedronGeometry(75.0, 1), material) + ..position.setValues(-200.0, 0.0, 200.0)); + + scene.add(new Mesh(new OctahedronGeometry(75.0, 2), material) + ..position.setValues(0.0, 0.0, 200.0)); + + scene.add(new Mesh(new TetrahedronGeometry(75.0, 0), material) + ..position.setValues(200.0, 0.0, 200.0)); + + scene.add(new Mesh(new PlaneGeometry(100.0, 100.0, 4, 4), material) + ..position.setValues(-400.0, 0.0, 0.0)); + + scene.add(new Mesh(new CubeGeometry(100.0, 100.0, 100.0, 4, 4, 4), material) + ..position.setValues(-200.0, 0.0, 0.0)); + + scene.add(new Mesh(new CircleGeometry(50.0, 20, 0.0, Math.PI * 2), material) + ..position.setValues(0.0, 0.0, 0.0)); + + scene.add(new Mesh(new RingGeometry(10.0, 50.0, 20, 5, 0.0, Math.PI * 2), material) + ..position.setValues(200.0, 0.0, 0.0)); + + scene.add(new Mesh(new CylinderGeometry(25.0, 75.0, 100.0, 40, 5), material) + ..position.setValues(400.0, 0.0, 0.0)); + + var points = new List.generate(50, (i) => + new Vector3(Math.sin(i * 0.2) * Math.sin(i * 0.1) * 15 + 50, 0.0, (i - 5) * 2.0)); + + scene.add(new Mesh(new LatheGeometry(points, 20), material) + ..position.setValues(-400.0, 0.0, -200.0)); + + scene.add(new Mesh(new TorusGeometry(50.0, 20.0, 20, 20), material) + ..position.setValues(-200.0, 0.0, -200.0)); + + scene.add(new Mesh(new TorusKnotGeometry(50.0, 10.0, 50, 20), material) + ..position.setValues(0.0, 0.0, -200.0)); + + scene.add(new DirectionalLight(0xffffff) + ..position.setValues(0.0, 1.0, 0.0)); + + scene.add(new AmbientLight(0x404040)); + + //scene.add(new AxisHelper(50.0)..position.setValues(200.0, 0.0, -200.0)); + + scene.add(new ArrowHelper(new Vector3(0.0, 1.0, 0.0), new Vector3.zero(), 50.0) + ..position.setValues(400.0, 0.0, -200.0)); + + renderer = new WebGLRenderer() + ..setSize(window.innerWidth, window.innerHeight); + container.append(renderer.domElement); + window.onResize.listen(onWindowResize); } -onWindowResize(event) { - +void onWindowResize(Event e) { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } -animate(num time) { +void animate(num time) { window.requestAnimationFrame(animate); render(); } -render() { - +void render() { var timer = new DateTime.now().millisecondsSinceEpoch * 0.0001; camera.position.x = Math.cos(timer) * 800.0; @@ -141,7 +113,6 @@ render() { object.rotation.x = timer * 5.0; object.rotation.y = timer * 2.5; }); - + renderer.render(scene, camera); - -} +} \ No newline at end of file diff --git a/example/web_gl_geometries2/UV_Grid_Sm.jpg b/example/web_gl_geometries2/UV_Grid_Sm.jpg new file mode 100644 index 00000000..bcc6ee1e Binary files /dev/null and b/example/web_gl_geometries2/UV_Grid_Sm.jpg differ diff --git a/example/web_gl_geometries2/webgl_geometries2.dart b/example/web_gl_geometries2/webgl_geometries2.dart new file mode 100644 index 00000000..8d9be571 --- /dev/null +++ b/example/web_gl_geometries2/webgl_geometries2.dart @@ -0,0 +1,109 @@ +/* + * Based on r70 + */ + +import 'dart:html'; +import 'dart:math' as Math; +import 'package:three/three.dart'; +import 'package:vector_math/vector_math.dart'; +import 'package:three/extras/image_utils.dart' as ImageUtils; +import 'package:three/extras/scene_utils.dart' as SceneUtils; +import 'package:three/extras/curve_extras.dart' as Curves; + +DivElement container; +WebGLRenderer renderer; +PerspectiveCamera camera; +Scene scene; + +void main() { + init(); + animate(0); +} + +void init() { + container = new DivElement(); + document.body.append(container); + + camera = new PerspectiveCamera(45.0, window.innerWidth / window.innerHeight, 1.0, 2000.0) + ..position.y = 400.0; + + scene = new Scene(); + + var map = ImageUtils.loadTexture('UV_Grid_Sm.jpg'); + map.wrapS = map.wrapT = RepeatWrapping; + map.anisotropy = 16; + + var materials = + [new MeshLambertMaterial(ambient: 0xbbbbbb, map: map, side: DoubleSide), + new MeshBasicMaterial(color: 0xffffff, wireframe: true, transparent: true, opacity: 0.1, side: DoubleSide)]; + + var torus2 = new ParametricGeometry.torusKnot(radius: 150.0, tube: 10.0, + segmentsR: 50, segmentsT: 20, p: 2.0 , q: 3.0, heightScale: 1.0); + + var sphere2 = new ParametricGeometry.sphere(75.0, 20, 10); + var tube2 = new ParametricGeometry.tube(new Curves.GrannyKnot(), segments: 150, radius: 2.0, closed: true); + + scene.add(SceneUtils.createMultiMaterialObject(new ParametricGeometry.klein(20, 20), materials) + ..position.setZero() + ..scale.scale(10.0)); + + scene.add(SceneUtils.createMultiMaterialObject(new ParametricGeometry.mobius(20, 20), materials) + ..position.setValues(10.0, 0.0, 0.0) + ..scale.scale(100.0)); + + scene.add(SceneUtils.createMultiMaterialObject(new ParametricGeometry.plane(200.0, 200.0, 10, 20), materials)); + + scene.add(SceneUtils.createMultiMaterialObject(torus2, materials) + ..position.setValues(0.0, 100.0, 0.0)); + + scene.add(SceneUtils.createMultiMaterialObject(sphere2, materials) + ..position.setValues(200.0, 0.0, 0.0)); + + scene.add(SceneUtils.createMultiMaterialObject(tube2, materials) + ..position.setValues(100.0, 0.0, 0.0)); + + scene.add(new AxisHelper(50.0)..position.setValues(200.0, 0.0, -200.0)); + + scene.add(new ArrowHelper(new Vector3(0.0, 1.0, 0.0), new Vector3.zero(), 50.0) + ..position.setValues(200.0, 0.0, 400.0)); + + scene.add(new AmbientLight(0x404040)); + + scene.add(new DirectionalLight(0xffffff) + ..position = new Vector3(0.0, 0.0, 1.0)); + + renderer = new WebGLRenderer() + ..setSize(window.innerWidth, window.innerHeight); + + container.append(renderer.domElement); + + window.onResize.listen(onWindowResize); +} + +void onWindowResize(Event e) { + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize(window.innerWidth, window.innerHeight); +} + +void animate(num time) { + window.requestAnimationFrame(animate); + render(); +} + +void render() { + var timer = new DateTime.now().millisecondsSinceEpoch * 0.0001; + + camera.position.x = Math.cos(timer) * 800.0; + camera.position.z = Math.sin(timer) * 800.0; + + camera.lookAt(scene.position); + + scene.children.forEach((object) { + object.rotation.x = timer * 5.0; + object.rotation.y = timer * 2.5; + }); + + renderer.render(scene, camera); +} \ No newline at end of file diff --git a/example/web_gl_geometries2/webgl_geometries2.html b/example/web_gl_geometries2/webgl_geometries2.html new file mode 100644 index 00000000..b3acb2f8 --- /dev/null +++ b/example/web_gl_geometries2/webgl_geometries2.html @@ -0,0 +1,20 @@ + + + + three.dart webgl - geometries + + + + + + + + + diff --git a/example/web_gl_geometry_extrude_by_u_shapes/web_gl_geometry_extrude_by_u_shapes.dart b/example/web_gl_geometry_extrude_by_u_shapes/web_gl_geometry_extrude_by_u_shapes.dart deleted file mode 100644 index 6eb3771f..00000000 --- a/example/web_gl_geometry_extrude_by_u_shapes/web_gl_geometry_extrude_by_u_shapes.dart +++ /dev/null @@ -1,300 +0,0 @@ -import 'dart:html'; -import 'dart:math' as Math; -import 'package:vector_math/vector_math.dart'; -import 'package:three/three.dart' as THREE; -import 'package:three/extras/scene_utils.dart' as SceneUtils; - -Element container; - -THREE.PerspectiveCamera camera; -THREE.Scene scene; -THREE.WebGLRenderer renderer; - -var windowHalfX, windowHalfY; -var mouseX = 0; -var mouseXOnMouseDown = 0; -var mouseEvts = []; - -var targetRotation = 0; -var targetRotationOnMouseDown = 0; - -THREE.Object3D parent, text, plane; - -void main() { - windowHalfX = window.innerWidth / 2; - windowHalfY = window.innerHeight / 2; - - init(); - animate(0); -} - -_addGeometry(geometry, color, x, y, z, rx, ry, rz, s) { - - // 3d shape - - var mesh = SceneUtils.createMultiMaterialObject( - geometry, - [ - new THREE.MeshLambertMaterial(color: color, opacity: 0.2, transparent: true), - new THREE.MeshBasicMaterial(color: 0x000000, wireframe: true, opacity: 0.3)]); - - mesh.position.setValues(x.toDouble(), y.toDouble(), z.toDouble() - 75); - // mesh.rotation.set( rx, ry, rz ); - double ds = s.toDouble(); - mesh.scale.setValues(ds, ds, ds); - - // if ( geometry.debug ) mesh.add( geometry.debug ); - - parent.add(mesh); - -} - -void init() { - - container = new Element.tag('div'); - document.body.nodes.add(container); - - camera = new THREE.PerspectiveCamera(50.0, window.innerWidth / window.innerHeight, 1.0, 1000.0); - camera.position.setValues(0.0, 150.0, 500.0); - - scene = new THREE.Scene(); - - var light = new THREE.DirectionalLight(0xffffff); - light.position.setValues(0.0, 0.0, 1.0); - scene.add(light); - - parent = new THREE.Object3D(); - parent.position.y = 50.0; - scene.add(parent); - - var extrudeAmount = 200, - extrudeBevelEnabled = true, - extrudeBevelSegments = 2; - - extrudeBevelEnabled = false; - - var pts = [], - starPoints = 5, - l; - - for (var i = 0; i < starPoints * 2; i++) { - - if (i % 2 == 1) { - - l = 5; - - } else { - - l = 10; - - } - - var a = i / starPoints * Math.PI; - pts.add(new Vector2(Math.cos(a) * l, Math.sin(a) * l)); - - } - - var starShape = new THREE.Shape(pts); - - var rnd = new Math.Random(); - - var line = new THREE.LineCurve3(new Vector3.zero(), new Vector3(100.0, 0.0, 0.0)); - var line2 = new THREE.LineCurve3(new Vector3(100.0, 0.0, 0.0), new Vector3(200.0, 50.0, 0.0)); - - var curvepath = new THREE.CurvePath(); - curvepath.add(line); - curvepath.add(line2); - - - var randomPoints = [new Vector3(200.0, 50.0, 0.0)]; - - for (var i = 0; i < 5; i++) { - - randomPoints.add(new Vector3(rnd.nextDouble() * 200, rnd.nextDouble() * 200, rnd.nextDouble() * 200)); - - } - - var randomSpline = new THREE.SplineCurve3(randomPoints); - curvepath.add(randomSpline); - - - - var extrudeUSteps = new List(); - var curvepathLength = curvepath.length; - var initU = 0; - var curveSteps = 40; - - for (var curve in curvepath.curves) { - - if (curve is THREE.LineCurve3) { - // Straight so we only need one step - initU += (curve.length ~/ curvepathLength); - extrudeUSteps.add(initU); - - } else { - // Not Straight so we subdivide the curve steps in 'curve_steps' divisions - for (var d = 0; d <= curveSteps; d++) { - extrudeUSteps.add(initU + ((d / curveSteps) * (curve.length / curvepathLength))); - } - initU = extrudeUSteps.last; - } - } - print("[WebGL_Geometry_Extrude_By_U_Shapes] ${extrudeUSteps}"); - - var extrude_extrudePath = curvepath; - - // Circle - - var circleRadius = 4.0; - var circleShape = new THREE.Shape(); - circleShape.moveTo(0, circleRadius); - circleShape.quadraticCurveTo(circleRadius, circleRadius, circleRadius, 0.0); - circleShape.quadraticCurveTo(circleRadius, -circleRadius, 0.0, -circleRadius); - circleShape.quadraticCurveTo(-circleRadius, -circleRadius, -circleRadius, 0.0); - circleShape.quadraticCurveTo(-circleRadius, circleRadius, 0.0, circleRadius); - - var rectLength = 12.0, - rectWidth = 4.0; - - var rectShape = new THREE.Shape(); - - rectShape.moveTo(-rectLength / 2, -rectWidth / 2); - rectShape.lineTo(-rectLength / 2, rectWidth / 2); - rectShape.lineTo(rectLength / 2, rectWidth / 2); - rectShape.lineTo(rectLength / 2, -rectLength / 2); - rectShape.lineTo(-rectLength / 2, -rectLength / 2); - - - // Smiley - - var smileyShape = new THREE.Shape(); - smileyShape.moveTo(80, 40); - smileyShape.arc(40, 40, 40, 0, Math.PI * 2, false); - - var smileyEye1Path = new THREE.Path(); - smileyEye1Path.moveTo(35, 20); - smileyEye1Path.arc(25, 20, 10, 0, Math.PI * 2, true); - smileyShape.holes.add(smileyEye1Path); - - var smileyEye2Path = new THREE.Path(); - smileyEye2Path.moveTo(65, 20); - smileyEye2Path.arc(55, 20, 10, 0, Math.PI * 2, true); - smileyShape.holes.add(smileyEye2Path); - - var smileyMouthPath = new THREE.Path(); - - smileyMouthPath.moveTo(20, 40); - smileyMouthPath.quadraticCurveTo(40, 60, 60, 40); - smileyMouthPath.bezierCurveTo(70, 45, 70, 50, 60, 60); - smileyMouthPath.quadraticCurveTo(40, 80, 20, 60); - smileyMouthPath.quadraticCurveTo(5, 50, 20, 40); - - smileyShape.holes.add(smileyMouthPath); - - var circle3d = starShape.extrude( - amount: extrudeAmount, - bevelSegments: extrudeBevelSegments, - bevelEnabled: extrudeBevelEnabled, - steps: extrudeUSteps, - extrudePath: extrude_extrudePath); //circleShape rectShape smileyShape starShape - // var circle3d = new ExtrudeGeometry(circleShape, extrudeBend, extrudeSettings ); - - var tube = new THREE.TubeGeometry(extrude_extrudePath, 40, 4.0, 5, false, true); - // new TubeGeometry(extrudePath, segments, 2, radiusSegments, closed2, debug); - - - _addGeometry(circle3d, 0xff1111, -100, 0, 0, 0, 0, 0, 1); - _addGeometry(tube, 0x00ff11, 0, 0, 0, 0, 0, 0, 1); - - renderer = new THREE.WebGLRenderer(); - renderer.setSize(window.innerWidth, window.innerHeight); - renderer.sortObjects = false; - - container.nodes.add(renderer.domElement); - - mouseEvts = [ - document.onMouseDown.listen(onDocumentMouseDown), - document.onTouchStart.listen(onDocumentTouchStart), - document.onTouchMove.listen(onDocumentTouchMove)]; - - window.onResize.listen(onWindowResize); -} - -onWindowResize(event) { - windowHalfX = window.innerWidth / 2; - windowHalfY = window.innerHeight / 2; - - camera.aspect = window.innerWidth / window.innerHeight; - camera.updateProjectionMatrix(); - - renderer.setSize(window.innerWidth, window.innerHeight); -} - -void cancelMouseEvts() { - mouseEvts.forEach((s) => s.cancel()); - mouseEvts = []; -} - -onDocumentMouseDown(MouseEvent event) { - event.preventDefault(); - - mouseEvts = [ - document.onMouseMove.listen(onDocumentMouseMove), - document.onMouseUp.listen(onDocumentMouseUp), - document.onMouseOut.listen(onDocumentMouseOut)]; - - mouseXOnMouseDown = event.client.x - windowHalfX; - targetRotationOnMouseDown = targetRotation; -} - -onDocumentMouseMove(MouseEvent event) { - mouseX = event.client.x - windowHalfX; - targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02; -} - -onDocumentMouseUp(event) { - cancelMouseEvts(); -} - -onDocumentMouseOut(event) { - cancelMouseEvts(); -} - -onDocumentTouchStart(TouchEvent event) { - - if (event.touches.length == 1) { - - event.preventDefault(); - - mouseXOnMouseDown = event.touches[0].page.x - windowHalfX; - targetRotationOnMouseDown = targetRotation; - - } - -} - -onDocumentTouchMove(TouchEvent event) { - - if (event.touches.length == 1) { - - event.preventDefault(); - - mouseX = event.touches[0].page.x - windowHalfX; - targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05; - - } - -} - -void animate(num time) { - window.requestAnimationFrame(animate); - render(); -} - -render() { - - parent.rotation.y += (targetRotation - parent.rotation.y) * 0.05; - - renderer.render(scene, camera); - -} diff --git a/example/web_gl_geometry_extrude_by_u_shapes/web_gl_geometry_extrude_by_u_shapes.html b/example/web_gl_geometry_extrude_by_u_shapes/web_gl_geometry_extrude_by_u_shapes.html deleted file mode 100644 index 19250dde..00000000 --- a/example/web_gl_geometry_extrude_by_u_shapes/web_gl_geometry_extrude_by_u_shapes.html +++ /dev/null @@ -1,16 +0,0 @@ - - - WebGL_Geometry_Extrude_Shapes - - - - - - - diff --git a/example/web_gl_geometry_extrude_shapes/web_gl_geometry_extrude_shapes.dart b/example/web_gl_geometry_extrude_shapes/web_gl_geometry_extrude_shapes.dart index c10c9c72..a02a1cea 100644 --- a/example/web_gl_geometry_extrude_shapes/web_gl_geometry_extrude_shapes.dart +++ b/example/web_gl_geometry_extrude_shapes/web_gl_geometry_extrude_shapes.dart @@ -1,8 +1,12 @@ +/* + * Based on r70 + */ + import 'dart:html' hide Path; import 'dart:math' as Math; import 'package:vector_math/vector_math.dart'; import 'package:three/three.dart'; -import 'package:three/extras/scene_utils.dart' as SceneUtils; +import 'package:three/extras/controls/trackball_controls.dart'; Element container; @@ -10,6 +14,8 @@ PerspectiveCamera camera; Scene scene; WebGLRenderer renderer; +TrackballControls controls; + var windowHalfX, windowHalfY; var mouseX = 0; var mouseXOnMouseDown = 0; @@ -28,216 +34,84 @@ void main() { animate(0); } -_addGeometry(geometry, color, x, y, z, rx, ry, rz, s) { - - // 3d shape - - var mesh = SceneUtils.createMultiMaterialObject( - geometry, - [ - new MeshLambertMaterial(color: color, opacity: 0.2, transparent: true), - new MeshBasicMaterial(color: 0x000000, wireframe: true, opacity: 0.3)]); - - mesh.position.setValues(x.toDouble(), y.toDouble(), z.toDouble() - 75); - // mesh.rotation.set( rx, ry, rz ); - double ds = s.toDouble(); - mesh.scale.setValues(ds, ds, ds); - - // if ( geometry.debug ) mesh.add( geometry.debug ); - - parent.add(mesh); - -} - void init() { - container = new Element.tag('div'); - document.body.nodes.add(container); - - camera = new PerspectiveCamera(50.0, window.innerWidth / window.innerHeight, 1.0, 1000.0); - camera.position.setValues(0.0, 150.0, 500.0); + document.body.append(container); + renderer = new WebGLRenderer() + ..setClearColorHex(0x222222, 1.0) + ..setSize(window.innerWidth, window.innerHeight); + container.append(renderer.domElement); + scene = new Scene(); - - var light = new DirectionalLight(0xffffff); - light.position.setValues(0.0, 0.0, 1.0); + + camera = new PerspectiveCamera(45.0, window.innerWidth / window.innerHeight, 1.0, 1000.0) + ..position.setValues(0.0, 0.0, 500.0); + + controls = new TrackballControls(camera, renderer.domElement); + controls.minDistance = 200.0; + controls.maxDistance = 500.0; + + scene.add(new AmbientLight(0x222222)); + var light = new PointLight(0xffffff); + light.position.setFrom(camera.position); + scene.add(light); - - parent = new Object3D(); - parent.position.y = 50.0; - scene.add(parent); - - var extrude_amount = 200, - extrude_bevelEnabled = true, - extrude_bevelSegments = 2, - extrude_steps = 150; // bevelSegments: 2, steps: 2 , bevelSegments: 5, bevelSize: 8, bevelThickness:5, - - // var extrudePath = new Path(); - - // extrudePath.moveTo( 0, 0 ); - // extrudePath.lineTo( 10, 10 ); - // extrudePath.quadraticCurveTo( 80, 60, 160, 10 ); - // extrudePath.quadraticCurveTo( 240, -40, 320, 10 ); - - - extrude_bevelEnabled = false; - - var extrudeBend = new SplineCurve3( //Closed - [ - new Vector3(30.0, 12.0, 83.0), - new Vector3(40.0, 20.0, 67.0), - new Vector3(60.0, 40.0, 99.0), - new Vector3(10.0, 60.0, 49.0), - new Vector3(25.0, 80.0, 40.0)]); - - var pipeSpline = new SplineCurve3( - [ - new Vector3(0.0, 10.0, -10.0), - new Vector3(10.0, 0.0, -10.0), - new Vector3(20.0, 0.0, 0.0), - new Vector3(30.0, 0.0, 10.0), - new Vector3(30.0, 0.0, 20.0), - new Vector3(20.0, 0.0, 30.0), - new Vector3(10.0, 0.0, 30.0), - new Vector3(0.0, 0.0, 30.0), - new Vector3(-10.0, 10.0, 30.0), - new Vector3(-10.0, 20.0, 30.0), - new Vector3(0.0, 30.0, 30.0), - new Vector3(10.0, 30.0, 30.0), - new Vector3(20.0, 30.0, 15.0), - new Vector3(10.0, 30.0, 10.0), - new Vector3(0.0, 30.0, 10.0), - new Vector3(-10.0, 20.0, 10.0), - new Vector3(-10.0, 10.0, 10.0), - new Vector3(0.0, 0.0, 10.0), - new Vector3(10.0, -10.0, 10.0), - new Vector3(20.0, -15.0, 10.0), - new Vector3(30.0, -15.0, 10.0), - new Vector3(40.0, -15.0, 10.0), - new Vector3(50.0, -15.0, 10.0), - new Vector3(60.0, 0.0, 10.0), - new Vector3(70.0, 0.0, 0.0), - new Vector3(80.0, 0.0, 0.0), - new Vector3(90.0, 0.0, 0.0), - new Vector3(100.0, 0.0, 0.0)]); - - var sampleClosedSpline = new ClosedSplineCurve3( - [ - new Vector3(0.0, -40.0, -40.0), - new Vector3(0.0, 40.0, -40.0), - new Vector3(0.0, 140.0, -40.0), - new Vector3(0.0, 40.0, 40.0), - new Vector3(0.0, -40.0, 40.0),]); - + + // + + var pts, geometry, material, mesh, shape; + + var closedSpline = new ClosedSplineCurve3( + [new Vector3(-60.0, -100.0, 60.0), + new Vector3(-60.0, 20.0, 60.0), + new Vector3(-60.0, 120.0, 60.0), + new Vector3( 60.0, 20.0, -60.0), + new Vector3( 60.0, -100.0, -60.0)]); + + pts = []; var count = 3; + for (var i = 0; i < count; i++) { + var l = 20; + var a = 2 * i / count * Math.PI; + pts.add(new Vector2 (Math.cos(a) * l, Math.sin(a) * l)); + } + + shape = new Shape(pts); + geometry = new ExtrudeGeometry(shape, steps: 100, bevelEnabled: false, extrudePath: closedSpline); + material = new MeshLambertMaterial(color: 0xb00000, wireframe: false); + mesh = new Mesh(geometry, material); + scene.add(mesh); + // var randomPoints = []; - var rnd = new Math.Random(); - - for (var i = 0; i < 10; i++) { - - randomPoints.add(new Vector3(rnd.nextDouble() * 200, rnd.nextDouble() * 200, rnd.nextDouble() * 200)); - + for (var i = 0; i < 10; i ++) { + randomPoints.add(new Vector3((i - 4.5) * 50, randFloat(- 50, 50), randFloat(- 50, 50))); } - - var randomSpline = new SplineCurve3(randomPoints); - - var extrude_extrudePath = randomSpline; // extrudeBend sampleClosedSpline pipeSpline randomSpline - - // Circle - - var circleRadius = 4.0; - var circleShape = new Shape(); - circleShape.moveTo(0, circleRadius); - circleShape.quadraticCurveTo(circleRadius, circleRadius, circleRadius, 0); - circleShape.quadraticCurveTo(circleRadius, -circleRadius, 0, -circleRadius); - circleShape.quadraticCurveTo(-circleRadius, -circleRadius, -circleRadius, 0); - circleShape.quadraticCurveTo(-circleRadius, circleRadius, 0, circleRadius); - - var rectLength = 12, - rectWidth = 4; - - var rectShape = new Shape(); - - rectShape.moveTo(-rectLength / 2, -rectWidth / 2); - rectShape.lineTo(-rectLength / 2, rectWidth / 2); - rectShape.lineTo(rectLength / 2, rectWidth / 2); - rectShape.lineTo(rectLength / 2, -rectLength / 2); - rectShape.lineTo(-rectLength / 2, -rectLength / 2); - - - var pts = [], - starPoints = 5, - l; - - for (var i = 0; i < starPoints * 2; i++) { - - if (i % 2 == 1) { - - l = 5; - - } else { - - l = 10; - - } - - var a = i / starPoints * Math.PI; + var randomSpline = new SplineCurve3(randomPoints); + + // + + pts = []; var numPts = 5; + for (var i = 0; i < numPts * 2; i++) { + var l = i % 2 == 1 ? 10 : 20; + var a = i / numPts * Math.PI; pts.add(new Vector2(Math.cos(a) * l, Math.sin(a) * l)); - } - - var starShape = new Shape(pts); - - // Smiley - - var smileyShape = new Shape(); - smileyShape.moveTo(80, 40); - smileyShape.arc(40, 40, 40, 0, Math.PI * 2, false); - - var smileyEye1Path = new Path(); - smileyEye1Path.moveTo(35, 20); - smileyEye1Path.arc(25, 20, 10, 0, Math.PI * 2, true); - smileyShape.holes.add(smileyEye1Path); - - var smileyEye2Path = new Path(); - smileyEye2Path.moveTo(65, 20); - smileyEye2Path.arc(55, 20, 10, 0, Math.PI * 2, true); - smileyShape.holes.add(smileyEye2Path); - - var smileyMouthPath = new Path(); - - smileyMouthPath.moveTo(20, 40); - smileyMouthPath.quadraticCurveTo(40, 60, 60, 40); - smileyMouthPath.bezierCurveTo(70, 45, 70, 50, 60, 60); - smileyMouthPath.quadraticCurveTo(40, 80, 20, 60); - smileyMouthPath.quadraticCurveTo(5, 50, 20, 40); - - smileyShape.holes.add(smileyMouthPath); - - var circle3d = starShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps, - extrudePath: extrude_extrudePath); //circleShape rectShape smileyShape starShape - // var circle3d = new ExtrudeGeometry(circleShape, extrudeBend, extrudeSettings ); - - var tube = new TubeGeometry(extrude_extrudePath, 150, 4.0, 5, false, true); - // new TubeGeometry(extrudePath, segments, 2, radiusSegments, closed2, debug); - - - _addGeometry(circle3d, 0xff1111, -100, 0, 0, 0, 0, 0, 1); - _addGeometry(tube, 0x00ff11, 0, 0, 0, 0, 0, 0, 1); - - renderer = new WebGLRenderer(); - renderer.setSize(window.innerWidth, window.innerHeight); - renderer.sortObjects = false; - - container.nodes.add(renderer.domElement); - - mouseEvts = [ - document.onMouseDown.listen(onDocumentMouseDown), - document.onTouchStart.listen(onDocumentTouchStart), - document.onTouchMove.listen(onDocumentTouchMove)]; + + shape = new Shape(pts); + geometry = new ExtrudeGeometry(shape, steps: 200, bevelEnabled: false, extrudePath: randomSpline); + var material2 = new MeshLambertMaterial(color: 0xff8000, wireframe: false); + mesh = new Mesh(geometry, material2); + scene.add(mesh); + + // + + var materials = [material, material2]; + + geometry = new ExtrudeGeometry(shape, amount: 20, steps: 1, material: 1, extrudeMaterial: 0, + bevelEnabled: true, bevelThickness: 2.0, bevelSize: 4.0, bevelSegments: 1); + mesh = new Mesh(geometry, new MeshFaceMaterial(materials)); + mesh.position.setValues(50.0, 100.0, 50.0); + scene.add(mesh); window.onResize.listen(onWindowResize); } @@ -252,71 +126,8 @@ onWindowResize(event) { renderer.setSize(window.innerWidth, window.innerHeight); } -void cancelMouseEvts() { - mouseEvts.forEach((s) => s.cancel()); - mouseEvts = []; -} - -onDocumentMouseDown(MouseEvent event) { - event.preventDefault(); - - mouseEvts = [ - document.onMouseMove.listen(onDocumentMouseMove), - document.onMouseUp.listen(onDocumentMouseUp), - document.onMouseOut.listen(onDocumentMouseOut)]; - - mouseXOnMouseDown = event.client.x - windowHalfX; - targetRotationOnMouseDown = targetRotation; -} - -onDocumentMouseMove(MouseEvent event) { - mouseX = event.client.x - windowHalfX; - targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02; -} - -onDocumentMouseUp(event) { - cancelMouseEvts(); -} - -onDocumentMouseOut(event) { - cancelMouseEvts(); -} - -onDocumentTouchStart(TouchEvent event) { - - if (event.touches.length == 1) { - - event.preventDefault(); - - mouseXOnMouseDown = event.touches[0].page.x - windowHalfX; - targetRotationOnMouseDown = targetRotation; - - } - -} - -onDocumentTouchMove(TouchEvent event) { - - if (event.touches.length == 1) { - - event.preventDefault(); - - mouseX = event.touches[0].page.x - windowHalfX; - targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05; - - } - -} - animate(num time) { window.requestAnimationFrame(animate); - render(); -} - -render() { - - parent.rotation.y += (targetRotation - parent.rotation.y) * 0.05; - + controls.update(); renderer.render(scene, camera); - -} +} \ No newline at end of file diff --git a/example/web_gl_geometry_shapes/web_gl_geometry_shapes.dart b/example/web_gl_geometry_shapes/web_gl_geometry_shapes.dart index add56f52..761e24af 100644 --- a/example/web_gl_geometry_shapes/web_gl_geometry_shapes.dart +++ b/example/web_gl_geometry_shapes/web_gl_geometry_shapes.dart @@ -1,9 +1,11 @@ +/* + * Based on r70 + */ + import 'dart:html' hide Path; import 'dart:math' as Math; import 'package:vector_math/vector_math.dart'; import 'package:three/three.dart'; -import 'package:three/extras/scene_utils.dart' as SceneUtils; -import 'package:three/extras/geometry_utils.dart' as GeometryUtils; Element container; @@ -19,7 +21,7 @@ var mouseEvts = []; var targetRotation = 0; var targetRotationOnMouseDown = 0; -Object3D parent, text, plane; +Object3D group, text, plane; void main() { windowHalfX = window.innerWidth / 2; @@ -29,401 +31,231 @@ void main() { animate(0); } -addGeometry(geometry, points, spacedPoints, color, x, y, z, rx, ry, rz, s) { - - // 3d shape - - var mesh = SceneUtils.createMultiMaterialObject( - geometry, - [new MeshLambertMaterial(color: color), new MeshBasicMaterial(color: 0x000000, wireframe: true, transparent: true)]); - mesh.position.setValues(x, y, z - 75); - mesh.rotation.setValues(rx, ry, rz); - mesh.scale.setValues(s, s, s); - parent.add(mesh); - - // solid line - - var line = new Line(points, new LineBasicMaterial(color: color, linewidth: 2)); - line.position.setValues(x, y, z + 25); - line.rotation.setValues(rx, ry, rz); - line.scale.setValues(s, s, s); - parent.add(line); - - // transparent line from real points - - line = new Line(points, new LineBasicMaterial(color: color, opacity: 0.5)); - line.position.setValues(x, y, z + 75); - line.rotation.setValues(rx, ry, rz); - line.scale.setValues(s, s, s); - parent.add(line); - - // vertices from real points - - var pgeo = GeometryUtils.clone(points); - var particles = new ParticleSystem(pgeo, new ParticleBasicMaterial(color: color, size: 2, opacity: 0.75)); - particles.position.setValues(x, y, z + 75); - particles.rotation.setValues(rx, ry, rz); - particles.scale.setValues(s, s, s); - parent.add(particles); - - // transparent line from equidistance sampled points - - line = new Line(spacedPoints, new LineBasicMaterial(color: color, opacity: 0.2)); - line.position.setValues(x, y, z + 100); - line.rotation.setValues(rx, ry, rz); - line.scale.setValues(s, s, s); - parent.add(line); - - // equidistance sampled points - - pgeo = GeometryUtils.clone(spacedPoints); - var particles2 = new ParticleSystem(pgeo, new ParticleBasicMaterial(color: color, size: 2, opacity: 0.5)); - particles2.position.setValues(x, y, z + 100); - particles2.rotation.setValues(rx, ry, rz); - particles2.scale.setValues(s, s, s); - parent.add(particles2); - -} - -roundedRect(ctx, x, y, width, height, radius) { - - ctx.moveTo(x, y + radius); - ctx.lineTo(x, y + height - radius); - ctx.quadraticCurveTo(x, y + height, x + radius, y + height); - ctx.lineTo(x + width - radius, y + height); - ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius); - ctx.lineTo(x + width, y + radius); - ctx.quadraticCurveTo(x + width, y, x + width - radius, y); - ctx.lineTo(x + radius, y); - ctx.quadraticCurveTo(x, y, x, y + radius); - -} void init() { - - container = new Element.tag('div'); - document.body.nodes.add(container); - - camera = new PerspectiveCamera(50.0, window.innerWidth / window.innerHeight, 1.0, 1000.0); - camera.position.setValues(0.0, 150.0, 500.0); + container = new DivElement(); + document.body.append(container); scene = new Scene(); - - var light = new DirectionalLight(0xffffff); - light.position.setValues(0.0, 0.0, 1.0); - scene.add(light); - - parent = new Object3D(); - parent.position.y = 50.0; - scene.add(parent); - - var extrude_amount = 20, - extrude_bevelEnabled = true, - extrude_bevelSegments = 2, - extrude_steps = 2; // bevelSegments: 2, steps: 2 , bevelSegments: 5, bevelsize: 8, bevelThickness:5, - + + camera = new PerspectiveCamera(50.0, window.innerWidth / window.innerHeight, 1.0, 1000.0) + ..position.setValues(0.0, 150.0, 500.0); + + scene.add(camera); + + var light = new PointLight(0xffffff, intensity: 0.8); + camera.add(light); + + group = new Object3D(); + group.position.y = 50.0; + scene.add(group); + + addShape(Shape shape, color, x, y, z, rx, ry, rz, s, + {amount: 8, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: 1.0, bevelThickness: 1.0}) { + x = x.toDouble(); y = y.toDouble(); z = z.toDouble(); rx = rx.toDouble(); ry = ry.toDouble(); rz = rz.toDouble(); s = s.toDouble(); + + var points = shape.createPointsGeometry(); + var spacedPoints = shape.createSpacedPointsGeometry(50); + // flat shape + + group.add(new Mesh(new ShapeGeometry(shape), new MeshPhongMaterial(color: color, side: DoubleSide)) + ..position.setValues(x, y, z - 125.0) + ..rotation.setValues(rx, ry, rz) + ..scale.setValues(s, s, s)); + + // 3d shape + group.add(new Mesh(new ExtrudeGeometry(shape, amount: amount, bevelEnabled: bevelEnabled, bevelSegments: bevelSegments, steps: steps, + bevelSize: bevelSize, bevelThickness: bevelThickness), new MeshPhongMaterial(color: color)) + ..position.setValues(x, y, z - 75.0) + ..rotation.setValues(rx, ry, rz) + ..scale.setValues(s, s, s)); + + // solid line + group.add(new Line(points, new LineBasicMaterial(color: color, linewidth: 3)) + ..position.setValues(x, y, z - 25.0) + ..rotation.setValues(rx, ry, rz) + ..scale.setValues(s, s, s)); + + // vertices from real points + group.add(new ParticleSystem(points.clone(), new ParticleBasicMaterial(color: color, size: 4)) + ..position.setValues(x, y, z + 25.0) + ..rotation.setValues(rx, ry, rz) + ..scale.setValues(s, s, s)); + + // line from equidistance sampled points + group.add(new Line(spacedPoints, new LineBasicMaterial(color: color, linewidth: 3)) + ..position.setValues(x, y, z + 75.0) + ..rotation.setValues(rx, ry, rz) + ..scale.setValues(s, s, s)); + + // equidistance sampled points + group.add(new ParticleSystem(spacedPoints.clone(), new ParticleBasicMaterial(color: color, size: 4)) + ..position.setValues(x, y, z + 125.0) + ..rotation.setValues(rx, ry, rz) + ..scale.setValues(s, s, s)); + } // California - var californiaPts = []; - - californiaPts.add(new Vector2(610.0, 320.0)); - californiaPts.add(new Vector2(450.0, 300.0)); - californiaPts.add(new Vector2(392.0, 392.0)); - californiaPts.add(new Vector2(266.0, 438.0)); - californiaPts.add(new Vector2(190.0, 570.0)); - californiaPts.add(new Vector2(190.0, 600.0)); - californiaPts.add(new Vector2(160.0, 620.0)); - californiaPts.add(new Vector2(160.0, 650.0)); - californiaPts.add(new Vector2(180.0, 640.0)); - californiaPts.add(new Vector2(165.0, 680.0)); - californiaPts.add(new Vector2(150.0, 670.0)); - californiaPts.add(new Vector2(90.0, 737.0)); - californiaPts.add(new Vector2(80.0, 795.0)); - californiaPts.add(new Vector2(50.0, 835.0)); - californiaPts.add(new Vector2(64.0, 870.0)); - californiaPts.add(new Vector2(60.0, 945.0)); - californiaPts.add(new Vector2(300.0, 945.0)); - californiaPts.add(new Vector2(300.0, 743.0)); - californiaPts.add(new Vector2(600.0, 473.0)); - californiaPts.add(new Vector2(626.0, 425.0)); - californiaPts.add(new Vector2(600.0, 370.0)); - californiaPts.add(new Vector2(610.0, 320.0)); - + californiaPts.add(new Vector2 (610.0, 320.0)); + californiaPts.add(new Vector2 (450.0, 300.0)); + californiaPts.add(new Vector2 (392.0, 392.0)); + californiaPts.add(new Vector2 (266.0, 438.0)); + californiaPts.add(new Vector2 (190.0, 570.0)); + californiaPts.add(new Vector2 (190.0, 600.0)); + californiaPts.add(new Vector2 (160.0, 620.0)); + californiaPts.add(new Vector2 (160.0, 650.0)); + californiaPts.add(new Vector2 (180.0, 640.0)); + californiaPts.add(new Vector2 (165.0, 680.0)); + californiaPts.add(new Vector2 (150.0, 670.0)); + californiaPts.add(new Vector2 ( 90.0, 737.0)); + californiaPts.add(new Vector2 ( 80.0, 795.0)); + californiaPts.add(new Vector2 ( 50.0, 835.0)); + californiaPts.add(new Vector2 ( 64.0, 870.0)); + californiaPts.add(new Vector2 ( 60.0, 945.0)); + californiaPts.add(new Vector2 (300.0, 945.0)); + californiaPts.add(new Vector2 (300.0, 743.0)); + californiaPts.add(new Vector2 (600.0, 473.0)); + californiaPts.add(new Vector2 (626.0, 425.0)); + californiaPts.add(new Vector2 (600.0, 370.0)); + californiaPts.add(new Vector2 (610.0, 320.0)); + for(var i = 0; i < californiaPts.length; i ++) { + californiaPts[i].scale(0.25); + } var californiaShape = new Shape(californiaPts); - - var california3d = new ExtrudeGeometry([californiaShape], amount: 20); - var californiaPoints = californiaShape.createPointsGeometry(); - var californiaSpacedPoints = californiaShape.createSpacedPointsGeometry(100); - + // Triangle - var triangleShape = new Shape(); - triangleShape.moveTo(80.0, 20.0); - triangleShape.lineTo(40.0, 80.0); + triangleShape.moveTo( 80.0, 20.0); + triangleShape.lineTo( 40.0, 80.0); triangleShape.lineTo(120.0, 80.0); - triangleShape.lineTo(80.0, 20.0); // close path - - var triangle3d = triangleShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var trianglePoints = triangleShape.createPointsGeometry(); - var triangleSpacedPoints = triangleShape.createSpacedPointsGeometry(); - - + triangleShape.lineTo( 80.0, 20.0); // close path + // Heart - - var x = 0.0, - y = 0.0; - + var x = 0.0, y = 0.0; var heartShape = new Shape(); // From http://blog.burlock.org/html5/130-paths - heartShape.moveTo(x + 25, y + 25); - heartShape.bezierCurveTo(x + 25, y + 25, x + 20, y, x, y); - heartShape.bezierCurveTo(x - 30, y, x - 30, y + 35, x - 30, y + 35); - heartShape.bezierCurveTo(x - 30, y + 55, x - 10, y + 77, x + 25, y + 95); - heartShape.bezierCurveTo(x + 60, y + 77, x + 80, y + 55, x + 80, y + 35); - heartShape.bezierCurveTo(x + 80, y + 35, x + 80, y, x + 50, y); - heartShape.bezierCurveTo(x + 35, y, x + 25, y + 25, x + 25, y + 25); - - var heart3d = heartShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var heartPoints = heartShape.createPointsGeometry(); - var heartSpacedPoints = heartShape.createSpacedPointsGeometry(); - - //heartShape.debug( document.getElementById("debug") ); - + heartShape.bezierCurveTo(x + 25.0, y + 25.0, x + 20.0, y, x, y); + heartShape.bezierCurveTo(x - 30.0, y, x - 30.0, y + 35.0, x - 30.0, y + 35.0); + heartShape.bezierCurveTo(x - 30.0, y + 55.0, x - 10.0, y + 77.0, x + 25.0, y + 95.0); + heartShape.bezierCurveTo(x + 60.0, y + 77.0, x + 80.0, y + 55.0, x + 80.0, y + 35.0); + heartShape.bezierCurveTo(x + 80.0, y + 35.0, x + 80.0, y, x + 50.0, y); + heartShape.bezierCurveTo(x + 35.0, y, x + 25.0, y + 25.0, x + 25.0, y + 25.0); + // Square - var sqLength = 80.0; - var squareShape = new Shape(); squareShape.moveTo(0.0, 0.0); squareShape.lineTo(0.0, sqLength); squareShape.lineTo(sqLength, sqLength); squareShape.lineTo(sqLength, 0.0); squareShape.lineTo(0.0, 0.0); - - var square3d = squareShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var squarePoints = squareShape.createPointsGeometry(); - var squareSpacedPoints = squareShape.createSpacedPointsGeometry(); - + // Rectangle - - var rectLength = 120.0, - rectWidth = 40.0; - + var rectLength = 120.0, rectWidth = 40.0; var rectShape = new Shape(); rectShape.moveTo(0.0, 0.0); rectShape.lineTo(0.0, rectWidth); rectShape.lineTo(rectLength, rectWidth); rectShape.lineTo(rectLength, 0.0); rectShape.lineTo(0.0, 0.0); - - var rect3d = rectShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var rectPoints = rectShape.createPointsGeometry(); - var rectSpacedPoints = rectShape.createSpacedPointsGeometry(); - + // Rounded rectangle - var roundedRectShape = new Shape(); - roundedRect(roundedRectShape, 0.0, 0.0, 50.0, 50.0, 20.0); - - var roundedRect3d = roundedRectShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var roundedRectPoints = roundedRectShape.createPointsGeometry(); - var roundedRectSpacedPoints = roundedRectShape.createSpacedPointsGeometry(); - + + ((Shape ctx, x, y, width, height, radius) { + ctx.moveTo(x, y + radius); + ctx.lineTo(x, y + height - radius); + ctx.quadraticCurveTo(x, y + height, x + radius, y + height); + ctx.lineTo(x + width - radius, y + height) ; + ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius); + ctx.lineTo(x + width, y + radius); + ctx.quadraticCurveTo(x + width, y, x + width - radius, y); + ctx.lineTo(x + radius, y); + ctx.quadraticCurveTo(x, y, x, y + radius); + })(roundedRectShape, 0.0, 0.0, 50.0, 50.0, 20.0); + + // Track + var trackShape = new Shape(); + trackShape.moveTo(40.0, 40.0); + trackShape.lineTo(40.0, 160.0); + trackShape.absarc(60.0, 160.0, 20.0, Math.PI, 0, true); + trackShape.lineTo(80.0, 40.0); + trackShape.absarc(60.0, 40.0, 20.0, 2 * Math.PI, Math.PI, true); + // Circle - var circleRadius = 40.0; var circleShape = new Shape(); circleShape.moveTo(0.0, circleRadius); - circleShape.quadraticCurveTo(circleRadius, circleRadius, circleRadius, 0.0); - circleShape.quadraticCurveTo(circleRadius, -circleRadius, 0.0, -circleRadius); - circleShape.quadraticCurveTo(-circleRadius, -circleRadius, -circleRadius, 0.0); - circleShape.quadraticCurveTo(-circleRadius, circleRadius, 0.0, circleRadius); - - var circle3d = circleShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var circlePoints = circleShape.createPointsGeometry(); - var circleSpacedPoints = circleShape.createSpacedPointsGeometry(); - + circleShape.quadraticCurveTo(circleRadius, circleRadius, circleRadius, 0); + circleShape.quadraticCurveTo(circleRadius, -circleRadius, 0, -circleRadius); + circleShape.quadraticCurveTo(-circleRadius, -circleRadius, -circleRadius, 0); + circleShape.quadraticCurveTo(-circleRadius, circleRadius, 0, circleRadius); + // Fish - - x = y = 0.0; - var fishShape = new Shape(); - + x = y = 0.0; fishShape.moveTo(x, y); - fishShape.quadraticCurveTo(x + 50, y - 80, x + 90, y - 10); - fishShape.quadraticCurveTo(x + 100, y - 10, x + 115, y - 40); - fishShape.quadraticCurveTo(x + 115, y, x + 115, y + 40); - fishShape.quadraticCurveTo(x + 100, y + 10, x + 90, y + 10); - fishShape.quadraticCurveTo(x + 50, y + 80, x, y); - - var fish3d = fishShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var fishPoints = fishShape.createPointsGeometry(); - var fishSpacedPoints = fishShape.createSpacedPointsGeometry(); - + fishShape.quadraticCurveTo(x + 50.0, y - 80.0, x + 90.0, y - 10.0); + fishShape.quadraticCurveTo(x + 100.0, y - 10.0, x + 115.0, y - 40.0); + fishShape.quadraticCurveTo(x + 115.0, y, x + 115.0, y + 40.0); + fishShape.quadraticCurveTo(x + 100.0, y + 10.0, x + 90.0, y + 10.0); + fishShape.quadraticCurveTo(x + 50.0, y + 80.0, x, y); + // Arc circle - var arcShape = new Shape(); arcShape.moveTo(50.0, 10.0); - arcShape.absarc(10.0, 10.0, 40.0, 0.0, Math.PI * 2, false); - + arcShape.absarc(10.0, 10.0, 40.0, 0.0, Math.PI*2, false); var holePath = new Path(); holePath.moveTo(20.0, 10.0); - holePath.absarc(10.0, 10.0, 10.0, 0.0, Math.PI * 2, true); + holePath.absarc(10.0, 10.0, 10.0, 0.0, Math.PI*2, true); arcShape.holes.add(holePath); - - var arc3d = arcShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var arcPoints = arcShape.createPointsGeometry(); - var arcSpacedPoints = arcShape.createSpacedPointsGeometry(); - - + // Smiley - var smileyShape = new Shape(); smileyShape.moveTo(80.0, 40.0); - smileyShape.absarc(40.0, 40.0, 40.0, 0.0, Math.PI * 2, false); - + smileyShape.absarc(40.0, 40.0, 40.0, 0.0, Math.PI*2, false); var smileyEye1Path = new Path(); smileyEye1Path.moveTo(35.0, 20.0); - // smileyEye1Path.absarc( 25, 20, 10, 0, Math.PI*2, true ); - smileyEye1Path.absellipse(25.0, 20.0, 10.0, 10.0, 0.0, Math.PI * 2, true); - - smileyShape.holes.add(smileyEye1Path); - + smileyEye1Path.absellipse(25.0, 20.0, 10.0, 10.0, 0.0, Math.PI*2, true); + smileyShape.holes.add(smileyEye1Path); var smileyEye2Path = new Path(); smileyEye2Path.moveTo(65.0, 20.0); - smileyEye2Path.absarc(55.0, 20.0, 10.0, 0.0, Math.PI * 2, true); - smileyShape.holes.add(smileyEye2Path); - + smileyEye2Path.absarc(55.0, 20.0, 10.0, 0.0, Math.PI*2, true); + smileyShape.holes.add(smileyEye2Path); var smileyMouthPath = new Path(); - // ugly box mouth - // smileyMouthPath.moveTo( 20, 40 ); - // smileyMouthPath.lineTo( 60, 40 ); - // smileyMouthPath.lineTo( 60, 60 ); - // smileyMouthPath.lineTo( 20, 60 ); - // smileyMouthPath.lineTo( 20, 40 ); - smileyMouthPath.moveTo(20.0, 40.0); smileyMouthPath.quadraticCurveTo(40.0, 60.0, 60.0, 40.0); smileyMouthPath.bezierCurveTo(70.0, 45.0, 70.0, 50.0, 60.0, 60.0); smileyMouthPath.quadraticCurveTo(40.0, 80.0, 20.0, 60.0); smileyMouthPath.quadraticCurveTo(5.0, 50.0, 20.0, 40.0); - smileyShape.holes.add(smileyMouthPath); - - - var smiley3d = smileyShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps); - var smileyPoints = smileyShape.createPointsGeometry(); - var smileySpacedPoints = smileyShape.createSpacedPointsGeometry(); - - // Spline shape + path extrusion - + + // Spline shape var splinepts = []; - splinepts.add(new Vector2(350.0, 100.0)); - splinepts.add(new Vector2(400.0, 450.0)); - splinepts.add(new Vector2(-140.0, 350.0)); - splinepts.add(new Vector2.zero()); - + splinepts.add(new Vector2 (70.0, 20.0)); + splinepts.add(new Vector2 (80.0, 90.0)); + splinepts.add(new Vector2 (-30.0, 70.0)); + splinepts.add(new Vector2 (0.0, 0.0)); var splineShape = new Shape(); splineShape.moveTo(0.0, 0.0); splineShape.splineThru(splinepts); - - //splineShape.debug( document.getElementById("debug") ); - - // TODO 3d path? - - var apath = new SplineCurve3(); - apath.points.add(new Vector3(-50.0, 150.0, 10.0)); - apath.points.add(new Vector3(-20.0, 180.0, 20.0)); - apath.points.add(new Vector3(40.0, 220.0, 50.0)); - apath.points.add(new Vector3(200.0, 290.0, 100.0)); - - var extrude_extrudePath = apath; - extrude_bevelEnabled = false; - extrude_steps = 20; - - var splineShape3d = splineShape.extrude( - amount: extrude_amount, - bevelSegments: extrude_bevelSegments, - bevelEnabled: extrude_bevelEnabled, - steps: extrude_steps, - extrudePath: extrude_extrudePath); - var splinePoints = splineShape.createPointsGeometry(); - var splineSpacedPoints = splineShape.createSpacedPointsGeometry(); - - addGeometry( - california3d, - californiaPoints, - californiaSpacedPoints, - 0xffaa00, - -300.0, - -100.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.25); - addGeometry(triangle3d, trianglePoints, triangleSpacedPoints, 0xffee00, -180.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); - addGeometry( - roundedRect3d, - roundedRectPoints, - roundedRectSpacedPoints, - 0x005500, - -150.0, - 150.0, - 0.0, - 0.0, - 0.0, - 0.0, - 1.0); - addGeometry(square3d, squarePoints, squareSpacedPoints, 0x0055ff, 150.0, 100.0, 0.0, 0.0, 0.0, 0.0, 1.0); - addGeometry(heart3d, heartPoints, heartSpacedPoints, 0xff1100, 0.0, 100.0, 0.0, Math.PI, 0.0, 0.0, 1.0); - addGeometry(circle3d, circlePoints, circleSpacedPoints, 0x00ff11, 120.0, 250.0, 0.0, 0.0, 0.0, 0.0, 1.0); - addGeometry(fish3d, fishPoints, fishSpacedPoints, 0x222222, -60.0, 200.0, 0.0, 0.0, 0.0, 0.0, 1.0); - addGeometry(splineShape3d, splinePoints, splineSpacedPoints, 0x888888, -50.0, -100.0, -50.0, 0.0, 0.0, 0.0, 0.2); - addGeometry(arc3d, arcPoints, arcSpacedPoints, 0xbb4422, 150.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); - addGeometry(smiley3d, smileyPoints, smileySpacedPoints, 0xee00ff, -270.0, 250.0, 0.0, Math.PI, 0.0, 0.0, 1.0); - - + + // addShape(shape, color, x, y, z, rx, ry,rz, s); + addShape(californiaShape, 0xf08000, -300, -100, 0, 0, 0, 0, 1); + addShape(triangleShape, 0x8080f0, -180, 0, 0, 0, 0, 0, 1); + addShape(roundedRectShape, 0x008000, -150, 150, 0, 0, 0, 0, 1); + addShape(trackShape, 0x008080, 200, -100, 0, 0, 0, 0, 1); + addShape(squareShape, 0x0040f0, 150, 100, 0, 0, 0, 0, 1); + addShape(heartShape, 0xf00000, 60, 100, 0, 0, 0, Math.PI, 1); + addShape(circleShape, 0x00f000, 120, 250, 0, 0, 0, 0, 1); + addShape(fishShape, 0x404040, -60, 200, 0, 0, 0, 0, 1); + addShape(smileyShape, 0xf000f0, -200, 250, 0, 0, 0, Math.PI, 1); + addShape(arcShape, 0x804000, 150, 0, 0, 0, 0, 0, 1); + addShape(splineShape, 0x808080, -50, -100, 0, 0, 0, 0, 1); // - renderer = new WebGLRenderer(); - renderer.setSize(window.innerWidth, window.innerHeight); - renderer.sortObjects = false; + renderer = new WebGLRenderer() + ..setClearColorHex(0xf0f0f0, 1.0) + ..setSize(window.innerWidth, window.innerHeight); container.nodes.add(renderer.domElement); @@ -477,29 +309,21 @@ onDocumentMouseOut(event) { } onDocumentTouchStart(TouchEvent event) { - if (event.touches.length == 1) { - event.preventDefault(); mouseXOnMouseDown = event.touches[0].page.x - windowHalfX; targetRotationOnMouseDown = targetRotation; - } - } onDocumentTouchMove(TouchEvent event) { - if (event.touches.length == 1) { - event.preventDefault(); mouseX = event.touches[0].page.x - windowHalfX; targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05; - } - } animate(num time) { @@ -508,9 +332,7 @@ animate(num time) { } render() { - - parent.rotation.y += (targetRotation - parent.rotation.y) * 0.05; + group.rotation.y += (targetRotation - group.rotation.y) * 0.05; renderer.render(scene, camera); - } diff --git a/example/web_gl_geometry_text/web_gl_geometry_text.dart b/example/web_gl_geometry_text/web_gl_geometry_text.dart index 935861ad..5cba8215 100644 --- a/example/web_gl_geometry_text/web_gl_geometry_text.dart +++ b/example/web_gl_geometry_text/web_gl_geometry_text.dart @@ -24,7 +24,7 @@ var firstLetter = true, curveSegments = 4, - bevelThickness = 2, + bevelThickness = 2.0, bevelSize = 1.5, bevelSegments = 3, bevelEnabled = true, @@ -202,7 +202,7 @@ createText() { textGeo = new TextGeometry( text, - height, + height.toInt(), false, bevelThickness, bevelSize, @@ -211,7 +211,6 @@ createText() { curveSegments, 1, null, - null, 0, 1, size, diff --git a/lib/extras/core/curve.dart b/lib/extras/core/curve.dart index 7f5e8612..8db62946 100644 --- a/lib/extras/core/curve.dart +++ b/lib/extras/core/curve.dart @@ -3,15 +3,21 @@ part of three; /************************************************************** * Abstract Curve base class **************************************************************/ -abstract class Curve { +class Curve { int _arcLengthDivisions = null; List cacheArcLengths = null; bool needsUpdate = false; + + Function _getPoint; + + Curve(); + + Curve.create(this._getPoint); // Virtual base class method to overwrite and implement in subclasses // - t [0 .. 1] - V getPoint(t); + V getPoint(double t) => _getPoint(t); // Get point at relative position in curve according to arc length // - u [0 .. 1] @@ -212,8 +218,8 @@ abstract class Curve { // Capping in case of danger - if (t1 < 0) t1 = 0; - if (t2 > 1) t2 = 1; + if (t1 < 0) t1 = 0.0; + if (t2 > 1) t2 = 1.0; var pt1 = getPoint(t1); var pt2 = getPoint(t2); diff --git a/lib/extras/core/shape.dart b/lib/extras/core/shape.dart index 2ff0c7d8..b2b61545 100644 --- a/lib/extras/core/shape.dart +++ b/lib/extras/core/shape.dart @@ -12,111 +12,39 @@ part of three; // STEP 3b - Triangulate each shape, add faces. class Shape extends Path { + List holes = []; - List holes; + Shape([List points]) : super(points); - Shape([List points]) - : holes = [], - super(points); - - // Convenience method to return ExtrudeGeometry - extrude({amount: 100, bevelThickness: 6.0, bevelSize: null, bevelSegments: 3, bevelEnabled: true, curveSegments: 12, - steps: 1, bendPath, extrudePath, material, extrudeMaterial}) { - - if (bevelSize == null) bevelSize = bevelThickness - 2.0; - - return new ExtrudeGeometry( - [this], - amount: amount, - bevelThickness: bevelThickness, - bevelSize: bevelSize, - bevelSegments: bevelSegments, - bevelEnabled: bevelEnabled, - curveSegments: curveSegments, - steps: steps, - bendPath: bendPath, - extrudePath: extrudePath, - material: material, - extrudeMaterial: extrudeMaterial); + /// Convenience method to return ExtrudeGeometry. + ExtrudeGeometry extrude({int amount: 100, double bevelThickness: 6.0, double bevelSize, int bevelSegments: 3, bool bevelEnabled: true, int curveSegments: 12, + steps: 1, Curve extrudePath, int material, int extrudeMaterial}) { + return new ExtrudeGeometry([this], amount: amount, bevelThickness: bevelThickness, bevelSize: bevelSize, bevelSegments: bevelSegments, bevelEnabled: bevelEnabled, + curveSegments: curveSegments, steps: steps, extrudePath: extrudePath, material: material, extrudeMaterial: extrudeMaterial); } - - - // Get points of holes - getPointsHoles(divisions) { - - var i, - il = holes.length; - var holesPts = new List(il); - - for (i = 0; i < il; i++) { - - holesPts[i] = holes[i].getTransformedPoints(divisions, bends: _bends); - - } - - return holesPts; - - } - - // Get points of holes (spaced by regular distance) - getSpacedPointsHoles(divisions) { - - var i, - il = holes.length; - var holesPts = new List(il); - - for (i = 0; i < il; i++) { - - holesPts[i] = holes[i].getTransformedSpacedPoints(divisions, _bends); - - } - - return holesPts; - - } - - - // Get points of shape and holes (keypoints based on segments parameter) - extractAllPoints(divisions) { - - return { - - "shape": getTransformedPoints(divisions), - "holes": getPointsHoles(divisions) - - }; - - } - - extractPoints([num divisions]) { - - if (useSpacedPoints) { - return extractAllSpacedPoints(divisions); - } - - return extractAllPoints(divisions); - - } - - // - // THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) { - // - // return { - // - // shape: this.transform( bend, divisions ), - // holes: this.getPointsHoles( divisions, bend ) - // - // }; - // - // }; - - // Get points of shape and holes (spaced by regular distance) - extractAllSpacedPoints([num divisions]) { - return { - "shape": getTransformedSpacedPoints(divisions), - "holes": getSpacedPointsHoles(divisions) - - }; - } - -} + + /// Convenience method to return ShapeGeometry. + ShapeGeometry makeGeometry({int curveSegments: 12, int material, ExtrudeGeometryWorldUVGenerator uvGenerator}) => + new ShapeGeometry([this], curveSegments: curveSegments, material: material, uvGenerator: uvGenerator); + + /// Get points of holes. + List> getPointsHoles(int divisions) => + new List.generate(holes.length, (i) => holes[i].getTransformedPoints(divisions)); + + /// Get points of holes (spaced by regular distance). + List> getSpacedPointsHoles(int divisions) => + new List.generate(holes.length, (i) => holes[i].getTransformedSpacedPoints(divisions)); + + /// Get points of shape and holes (keypoints based on segments parameter). + Map extractAllPoints(int divisions) => + {"shape": getTransformedPoints(divisions), + "holes": getPointsHoles(divisions)}; + + Map extractPoints([int divisions]) => + useSpacedPoints ? extractAllSpacedPoints(divisions) : extractAllPoints(divisions); + + /// Get points of shape and holes (spaced by regular distance). + Map extractAllSpacedPoints([int divisions]) => + {"shape": getTransformedSpacedPoints(divisions), + "holes": getSpacedPointsHoles(divisions)}; +} \ No newline at end of file diff --git a/lib/extras/curve_extras.dart b/lib/extras/curve_extras.dart new file mode 100644 index 00000000..ecfb7d6a --- /dev/null +++ b/lib/extras/curve_extras.dart @@ -0,0 +1,215 @@ +library CurveExtras; + +import 'dart:math' as Math; +import 'package:three/three.dart' show Curve3D; +import 'package:vector_math/vector_math.dart'; + +class GrannyKnot extends Curve3D { + Vector3 getPoint(double t) { + t = 2 * Math.PI * t; + + var x = -0.22 * Math.cos(t) - 1.28 * Math.sin(t) - 0.44 * Math.cos(3 * t) - 0.78 * Math.sin(3 * t); + var y = -0.1 * Math.cos(2 * t) - 0.27 * Math.sin(2 * t) + 0.38 * Math.cos(4 * t) + 0.46 * Math.sin(4 * t); + var z = 0.7 * Math.cos(3 * t) - 0.4 * Math.sin(3 * t); + + return new Vector3(x, y, z)..scale(20.0); + } +} + +class HeartCurve extends Curve3D { + double scale; + + HeartCurve([this.scale = 5.0]); + + Vector3 getPoint(double t) { + t *= 2 * Math.PI; + + var tx = 16 * Math.pow(Math.sin(t), 3); + var ty = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t); + + return new Vector3(tx, ty, 0.0)..scale(scale); + } +} + +class VivianiCurve extends Curve3D { + double radius; + + VivianiCurve(this.radius); + + Vector3 getPoint(double t) { + t = t * 4 * Math.PI; // Normalized to 0..1 + var a = radius / 2; + var tx = a * (1 + Math.cos(t)), + ty = a * Math.sin(t), + tz = 2 * a * Math.sin(t / 2); + + return new Vector3(tx, ty, tz); + } +} + +class KnotCurve extends Curve3D { + Vector3 getPoint(double t) { + t *= 2 * Math.PI; + + var R = 10; + var s = 50; + var tx = s * Math.sin(t), + ty = Math.cos(t) * (R + s * Math.cos(t)), + tz = Math.sin(t) * (R + s * Math.cos(t)); + + return new Vector3(tx, ty, tz); + } +} + +class HelixCurve extends Curve3D { + Vector3 getPoint(double t) { + var radius = 30; + var height = 150; + var t2 = 2 * Math.PI * t * height / 30; + var tx = Math.cos(t2) * radius, + ty = Math.sin(t2) * radius, + tz = height * t; + + return new Vector3(tx, ty, tz); + } +} + +class TrefoilKnot extends Curve3D { + double scale; + + TrefoilKnot([this.scale = 10.0]); + + Vector3 getPoint(double t) { + t *= Math.PI * 2; + var tx = (2 + Math.cos(3 * t)) * Math.cos(2 * t), + ty = (2 + Math.cos(3 * t)) * Math.sin(2 * t), + tz = Math.sin(3 * t); + + return new Vector3(tx, ty, tz)..scale(scale); + } +} + +class TorusKnot extends Curve3D { + double scale; + + TorusKnot([double scale = 10.0]); + + Vector3 getPoint(double t) { + var p = 3, q = 4; + t *= Math.PI * 2; + var tx = (2 + Math.cos(q * t)) * Math.cos(p * t), + ty = (2 + Math.cos(q * t)) * Math.sin(p * t), + tz = Math.sin(q * t); + + return new Vector3(tx, ty, tz)..scale(scale); + } +} + +class CinquefoilKnot extends Curve3D { + double scale; + + CinquefoilKnot([this.scale = 10.0]); + + Vector3 getPoint(double t) { + var p = 2, q = 5; + t *= Math.PI * 2; + var tx = (2 + Math.cos(q * t)) * Math.cos(p * t), + ty = (2 + Math.cos(q * t)) * Math.sin(p * t), + tz = Math.sin(q * t); + + return new Vector3(tx, ty, tz)..scale(scale); + } +} + +class TrefoilPolynomialKnot extends Curve3D { + double scale; + + TrefoilPolynomialKnot([this.scale = 10.0]); + + Vector3 getPoint(double t) { + t = t * 4 - 2; + var tx = Math.pow(t, 3) - 3 * t, + ty = Math.pow(t, 4) - 4 * t * t, + tz = 1 / 5 * Math.pow(t, 5) - 2 * t; + + return new Vector3(tx, ty, tz)..scale(scale); + } +} + +class FigureEightPolynomialKnot extends Curve3D { + double scale; + + FigureEightPolynomialKnot([this.scale = 1.0]); + + Vector3 getPoint(double t) { + var scaleTo = (x, y, t) => t * (y - x) * x; + t = scaleTo(-4.0, 4.0, t); + var tx = 2 / 5 * t * (t * t - 7) * (t * t - 10), + ty = Math.pow(t, 4) - 13 * t * t, + tz = 1 / 10 * t * (t * t - 4) * (t * t - 9) * (t * t - 12); + + return new Vector3(tx, ty, tz)..scale(scale); + } +} + +class DecoratedTorusKnot4a extends Curve3D { + double scale; + + DecoratedTorusKnot4a([this.scale = 40.0]); + + Vector3 getPoint(double t) { + t *= Math.PI * 2; + var x = Math.cos(2 * t) * (1 + 0.6 * (Math.cos(5 * t) + 0.75 * Math.cos(10 * t))), + y = Math.sin(2 * t) * (1 + 0.6 * (Math.cos(5 * t) + 0.75 * Math.cos(10 * t))), + z = 0.35 * Math.sin(5 * t); + + return new Vector3(x, y, z)..scale(scale); + } +} + +class DecoratedTorusKnot4b extends Curve3D { + double scale; + + DecoratedTorusKnot4b([this.scale = 40.0]); + + Vector3 getPoint(double t) { + var fi = t * Math.PI * 2; + var x = Math.cos(2 * fi) * (1 + 0.45 * Math.cos(3 * fi) + 0.4 * Math.cos(9 * fi)), + y = Math.sin(2 * fi) * (1 + 0.45 * Math.cos(3 * fi) + 0.4 * Math.cos(9 * fi)), + z = 0.2 * Math.sin(9 * fi); + + return new Vector3(x, y, z).scale(scale); + } +} + +class DecoratedTorusKnot5a extends Curve3D { + double scale; + + DecoratedTorusKnot5a([this.scale = 40.0]); + + Vector3 getPoint(double t) { + var fi = t * Math.PI * 2; + var x = Math.cos(3 * fi) * (1 + 0.3 * Math.cos(5 * fi) + 0.5 * Math.cos(10 * fi)), + y = Math.sin(3 * fi) * (1 + 0.3 * Math.cos(5 * fi) + 0.5 * Math.cos(10 * fi)), + z = 0.2 * Math.sin(20 * fi); + + return new Vector3(x, y, z)..scale(scale); + } +} + +class DecoratedTorusKnot5c extends Curve3D { + double scale; + + DecoratedTorusKnot5c([this.scale = 40.0]); + + Vector3 getPoint(double t) { + var fi = t * Math.PI * 2; + var x = Math.cos(4 * fi) * (1 + 0.5 * (Math.cos(5 * fi) + 0.4 * Math.cos(20 * fi))), + y = Math.sin(4 * fi) * (1 + 0.5 * (Math.cos(5 * fi) + 0.4 * Math.cos(20 * fi))), + z = 0.35 * Math.sin(15 * fi); + + return new Vector3(x, y, z)..scale(scale); + } +} + + diff --git a/lib/extras/geometries/circle_geometry.dart b/lib/extras/geometries/circle_geometry.dart index 6f364328..609faa99 100644 --- a/lib/extras/geometries/circle_geometry.dart +++ b/lib/extras/geometries/circle_geometry.dart @@ -1,49 +1,60 @@ +/* + * @author hughes + * + * based on r70 + */ + part of three; +/** + * CircleGeometry is a simple shape of Euclidean geometry. It is contructed + * from a number of triangular segments that are oriented around a central + * point and extend as far out as a given radius. It is built counter-clockwise + * from a start angle and a given central angle. It can also be used to create + * regular polygons, where the number of segments determines the number of sides. + * + * var material = new THREE.MeshBasicMaterial(color: 0x0000ff); + * + * var radius = 5, segments = 32; + * var circleGeometry = new CircleGeometry(radius, segments); + * var circle = new Mesh(circleGeometry, material); + * scene.add(circle); + */ class CircleGeometry extends Geometry { - num radius, segments, thetaStart, thetaLength; - - CircleGeometry([this.radius = 50, this.segments = 8, this.thetaStart = 0, this.thetaLength = Math.PI * 2]) : super() { - segments = Math.max(3, segments); - - var i, - uvs = [], - center = new Vector3.zero(), - centerUV = new UV(0.5, 0.5); + String type = 'CircleGeometry'; + + /// Creates a new circle geometry. + CircleGeometry([double radius = 50.0, + int segments, + double thetaStart = 0.0, + double thetaLength = Math.PI * 2]) { + segments = segments != null ? Math.max(3, segments) : 8; + + List uvs = []; + var center = new Vector3.zero(); + var centerUV = new Vector2(0.5, 0.5); vertices.add(center); uvs.add(centerUV); - for (i = 0; i <= segments; i++) { - + for (var i = 0; i <= segments; i++) { var vertex = new Vector3.zero(); - vertex.x = radius * Math.cos(thetaStart + i / segments * thetaLength); vertex.y = radius * Math.sin(thetaStart + i / segments * thetaLength); - + vertices.add(vertex); - uvs.add(new UV((vertex.x / radius + 1) / 2, -(vertex.y / radius + 1) / 2 + 1)); - + uvs.add(new Vector2((vertex.x / radius + 1) / 2, -(vertex.y / radius + 1) / 2 + 1)); } - - var n = new Vector3(0.0, 0.0, -1.0); - - for (i = 1; i <= segments; i++) { - - var v1 = i; - var v2 = i + 1; - var v3 = 0; - - faces.add(new Face3(v1, v2, v3, [n, n, n])); - faceVertexUvs[0].add([uvs[i], uvs[i + 1], centerUV]); - + + var n = new Vector3(0.0, 0.0, 1.0); + + for (var i = 1; i <= segments; i++) { + faces.add(new Face3(i, i + 1, 0, [n.clone(), n.clone(), n.clone()])); + faceVertexUvs[0].add([uvs[i].clone(), uvs[i + 1].clone(), centerUV.clone()]); } - computeCentroids(); computeFaceNormals(); boundingSphere = new BoundingSphere(radius: radius); - } - } diff --git a/lib/extras/geometries/convex_geometry.dart b/lib/extras/geometries/convex_geometry.dart index e01ec7b7..721d0902 100644 --- a/lib/extras/geometries/convex_geometry.dart +++ b/lib/extras/geometries/convex_geometry.dart @@ -1,180 +1,132 @@ -part of three; - -class ConvexGeometry extends Geometry { - ConvexGeometry(List vertices) : super() { - - var faces = [[0, 1, 2], [0, 2, 1]]; - - var addPoint = (vertexId) { - - var vertex = vertices[vertexId].clone(); - - var mag = vertex.length(); - vertex.x += mag * _randomOffset(); - vertex.y += mag * _randomOffset(); - vertex.z += mag * _randomOffset(); - - List hole = []; - - for (var f = 0; f < faces.length; ) { - - var face = faces[f]; - - // for each face, if the vertex can see it, - // then we try to add the face's edges into the hole. - if (_visible(face, vertex)) { - - for (var e = 0; e < 3; e++) { - - var edge = [face[e], face[(e + 1) % 3]]; - var boundary = true; - - // remove duplicated edges. - for (var h = 0; h < hole.length; h++) { - - if (_equalEdge(hole[h], edge)) { - - hole[h] = hole[hole.length - 1]; - hole.removeLast(); - boundary = false; - break; - - } - - } +/* + * Based on r66 + */ - if (boundary) { - - hole.add(edge); - - } - - } - - // remove faces[ f ] - faces[f] = faces[faces.length - 1]; - faces.removeLast(); - - } else { // not visible - - f++; - - } - } - - // construct the new faces formed by the edges of the hole and the vertex - for (var h = 0; h < hole.length; h++) { - - faces.add([hole[h][0], hole[h][1], vertexId]); - - } - }; +part of three; - for (var i = 3; i < vertices.length; i++) { - addPoint(i); +/// A convex hull generator using the incremental method. +/// The complexity is O(n^2) where n is the number of vertices. +/// O(nlogn) algorithms do exist, but they are much more complicated. +class ConvexGeometry extends Geometry { + List _vertices; + List> _faces = [[0, 1, 2], [0, 2, 1]]; + + ConvexGeometry(this._vertices) : super() { + for (var i = 3; i < _vertices.length; i++) { + _addPoint(i); } - - + // Push vertices into `this.vertices`, skipping those inside the hull var id = 0; - var newId = new List(vertices.length); // map from old vertex id to new id - - for (var i = 0; i < faces.length; i++) { - - var face = faces[i]; + var newId = new List(_vertices.length); // map from old vertex id to new id + for (var i = 0; i < _faces.length; i++) { + var face = _faces[i]; for (var j = 0; j < 3; j++) { if (newId[face[j]] == null) { - newId[face[j]] = id++; - this.vertices.add(vertices[face[j]]); - + vertices.add(_vertices[face[j]]); } + face[j] = newId[face[j]]; } } - - // Convert faces into instances of THREE.Face3 - for (var i = 0; i < faces.length; i++) { - - this.faces.add(new Face3(faces[i][0], faces[i][1], faces[i][2])); - - } + + // Convert faces into instances of Face3 + faces = new List.generate(_faces.length, (i) => + new Face3(_faces[i][0], + _faces[i][1], + _faces[i][2])); // Compute UVs - for (var i = 0; i < this.faces.length; i++) { - - var face = this.faces[i]; + faceVertexUvs[0] = new List.generate(faces.length, (i) => + [_vertexUv(vertices[(faces[i] as Face3).a]), + _vertexUv(vertices[(faces[i] as Face3).b]), + _vertexUv(vertices[(faces[i] as Face3).c])]); + + computeFaceNormals(); + computeVertexNormals(); + } + + void _addPoint(int vertexId) { + var vertex = _vertices[vertexId].clone(); + + var mag = vertex.length; + vertex.x += mag * _randomOffset(); + vertex.y += mag * _randomOffset(); + vertex.z += mag * _randomOffset(); + + var hole = []; + + for (var f = 0; f < _faces.length;) { + var face = _faces[f]; + + // for each face, if the vertex can see it, + // then we try to add the face's edges into the hole. + if (_visible(face, vertex)) { + for ( var e = 0; e < 3; e++ ) { + var edge = [face[e], face[(e + 1) % 3]]; + var boundary = true; + + // remove duplicated edges. + for (var h = 0; h < hole.length; h++) { + if (_equalEdge(hole[h], edge)) { + hole[h] = hole[hole.length - 1]; + hole.removeLast(); + boundary = false; + break; + } + } - this.faceVertexUvs[0].add( - [_vertexUv(this.vertices[face.a]), _vertexUv(this.vertices[face.b]), _vertexUv(this.vertices[face.c])]); + if (boundary) { + hole.add(edge); + } + } + _faces[f] = _faces[_faces.length - 1]; + _faces.removeLast(); + } else { // not visible + f++; + } } - - this.computeCentroids(); - this.computeFaceNormals(); - this.computeVertexNormals(); + // construct the new faces formed by the edges of the hole and the vertex + for (var h = 0; h < hole.length; h++) { + _faces.add([hole[h][0], + hole[h][1], + vertexId]); + } } - - /** - * Whether the face is visible from the vertex - */ + + // Whether the face is visible from the vertex. bool _visible(List face, Vector3 vertex) { - - var va = vertices[face[0]]; - var vb = vertices[face[1]]; - var vc = vertices[face[2]]; + var va = _vertices[face[0]]; + var vb = _vertices[face[1]]; + var vc = _vertices[face[2]]; var n = _normal(va, vb, vc); // distance from face to origin var dist = n.dot(va); - return n.dot(vertex) >= dist; - + return n.dot(vertex) >= dist; } - /** - * Face normal - */ - Vector3 _normal(Vector3 va, Vector3 vb, Vector3 vc) { - - Vector3 cb = new Vector3.zero(); - Vector3 ab = new Vector3.zero(); - - cb = vc - vb; - ab = va - vb; - cb = cb.cross(ab); - cb.normalize(); - - return cb; + // Face normal + Vector3 _normal(Vector3 va, Vector3 vb, Vector3 vc) => + (vc - vb).cross(va - vb).normalize(); - } - - /** + /* * Detect whether two edges are equal. * Note that when constructing the convex hull, two same edges can only * be of the negative direction. */ - _equalEdge(ea, eb) => ea[0] == eb[1] && ea[1] == eb[0]; - - - /** - * Create a random offset between -1e-6 and 1e-6. - */ - _randomOffset() => (new Math.Random().nextDouble() - 0.5) * 2 * 1e-6; + bool _equalEdge(List ea, List eb) => ea[0] == eb[1] && ea[1] == eb[0]; + // Create a random offset between -1e-6 and 1e-6. + double _randomOffset() => ThreeMath.randFloat(-1e-6, 1e-6); - /** - * XXX: Not sure if this is the correct approach. Need someone to review. - */ - _vertexUv(vertex) { - - var mag = vertex.length(); - return new UV(vertex.x / mag, vertex.y / mag); - - } -} + Vector2 _vertexUv(vertex) => new Vector2(vertex.x / vertex.length, vertex.y / vertex.length); +} \ No newline at end of file diff --git a/lib/extras/geometries/cube_geometry.dart b/lib/extras/geometries/cube_geometry.dart index 652b98bf..7f5cedf4 100644 --- a/lib/extras/geometries/cube_geometry.dart +++ b/lib/extras/geometries/cube_geometry.dart @@ -98,7 +98,7 @@ class CubeGeometry extends Geometry { Vector3 normal = new Vector3.zero(); //TODO: find out how to do this sort of casting in Dart... - // normal.dynamic[ w ] = depth > 0 ? 1 : - 1; + // normal.dynamic[w] = depth > 0 ? 1 : - 1; if (w == 'x') { normal.x = depth > 0 ? 1.0 : -1.0; @@ -110,9 +110,9 @@ class CubeGeometry extends Geometry { for (int ix = 0; ix < gridX1; ix++) { Vector3 vector = new Vector3.zero(); //TODO: find out how to do this sort of casting in Dart... -// vector[ u ] = ( ix * segment_width - width_half ) * udir; -// vector[ v ] = ( iy * segment_height - height_half ) * vdir; -// vector[ w ] = depth; +// vector[u] = (ix * segment_width - width_half) * udir; +// vector[v] = (iy * segment_height - height_half) * vdir; +// vector[w] = depth; if (u == 'x') { vector.x = (ix * segment_width - width_half) * udir; @@ -143,22 +143,26 @@ class CubeGeometry extends Geometry { num c = (ix + 1) + gridX1 * (iy + 1); num d = (ix + 1) + gridX1 * iy; - Face4 face = new Face4(a + offset, b + offset, c + offset, d + offset); + var uva = new Vector2(ix / gridX, 1 - iy / gridY); + var uvb = new Vector2(ix / gridX, 1 - (iy + 1) / gridY); + var uvc = new Vector2((ix + 1) / gridX, 1 - (iy + 1) / gridY); + var uvd = new Vector2((ix + 1) / gridX, 1 - iy / gridY); + + var face = new Face3(a + offset, b + offset, d + offset); face.normal.setFrom(normal); - face.vertexNormals.addAll([normal.clone(), normal.clone(), normal.clone(), normal.clone()]); + face.vertexNormals.addAll([normal.clone(), normal.clone(), normal.clone()]); face.materialIndex = material; faces.add(face); + faceVertexUvs[0].add([uva, uvb, uvd]); + + face = new Face3(b + offset, c + offset, d + offset); + face.normal.setFrom(normal); + face.vertexNormals.addAll([normal.clone(), normal.clone(), normal.clone()]); + face.materialIndex = material; - List faceVertexUV = faceVertexUvs[0]; - List newUVs = new List(); - newUVs.addAll( - [ - new UV(ix / gridX, 1 - iy / gridY), - new UV(ix / gridX, 1 - (iy + 1) / gridY), - new UV((ix + 1) / gridX, 1 - (iy + 1) / gridY), - new UV((ix + 1) / gridX, 1 - iy / gridY)]); - faceVertexUV.add(newUVs); + faces.add(face); + faceVertexUvs[0].add([uvb.clone(), uvc, uvd.clone()]); } } } @@ -172,4 +176,3 @@ class CubeGeomSides { } - diff --git a/lib/extras/geometries/cylinder_geometry.dart b/lib/extras/geometries/cylinder_geometry.dart index 86bb67e9..cc1564e1 100644 --- a/lib/extras/geometries/cylinder_geometry.dart +++ b/lib/extras/geometries/cylinder_geometry.dart @@ -1,81 +1,85 @@ +/* + * @author mrdoob / http://mrdoob.com/ + * + * based on r70 + */ + part of three; +/** + * A class for generating cylinder geometries + * + * var geometry = new CylinderGeometry(5.0, 5.0, 20, 32); + * var material = new MeshBasicMaterial(color: 0xffff00); + * var cylinder = new Mesh(geometry, material); + * scene.add(cylinder); + */ class CylinderGeometry extends Geometry { - double radiusTop, radiusBottom, height; - int segmentsRadius, segmentsHeight; - bool openEnded; - - CylinderGeometry([this.radiusTop = 20.0, this.radiusBottom = 20.0, this.height = 100.0, this.segmentsRadius = 8, - this.segmentsHeight = 1, this.openEnded = false]) - : super() { + String type = 'CylinderGeometry'; + + /// Creates a new cylinder geometry. + CylinderGeometry([double radiusTop = 20.0, + double radiusBottom = 20.0, + double height = 100.0, + int radialSegments = 8, + int heightSegments = 1, + bool openEnded = false, + double thetaStart = 0.0, + double thetaLength = 2 * Math.PI]) : super() { double heightHalf = height / 2; - int segmentsX = segmentsRadius; - int segmentsY = segmentsHeight; - - int x, y; - - List vertices = [], - uvs = []; - - for (y = 0; y <= segmentsY; y++) { + + List> vertices = []; + List> uvs = []; + for (var y = 0; y <= heightSegments; y++) { var verticesRow = []; var uvsRow = []; - double v = y / segmentsY; + double v = y / heightSegments; var radius = v * (radiusBottom - radiusTop) + radiusTop; - for (x = 0; x <= segmentsX; x++) { - - double u = x / segmentsX; - - var vertex = new Vector3.zero(); - vertex.x = radius * Math.sin(u * Math.PI * 2); - vertex.y = -v * height + heightHalf; - vertex.z = radius * Math.cos(u * Math.PI * 2); - + for (var x = 0; x <= radialSegments; x++) { + double u = x / radialSegments; + + var vertex = new Vector3.zero() + ..x = radius * Math.sin(u * thetaLength + thetaStart) + ..y = -v * height + heightHalf + ..z = radius * Math.cos(u * thetaLength + thetaStart); + this.vertices.add(vertex); - + verticesRow.add(this.vertices.length - 1); - uvsRow.add(new UV(u, 1 - v)); - + uvsRow.add(new Vector2(u, 1 - v)); } vertices.add(verticesRow); uvs.add(uvsRow); - } var tanTheta = (radiusBottom - radiusTop) / height; var na, nb; - for (x = 0; x < segmentsX; x++) { - + for (var x = 0; x < radialSegments; x++) { if (radiusTop != 0) { - na = this.vertices[vertices[0][x]].clone(); nb = this.vertices[vertices[0][x + 1]].clone(); - } else { - na = this.vertices[vertices[1][x]].clone(); nb = this.vertices[vertices[1][x + 1]].clone(); - } - na[1] = Math.sqrt(na.x * na.x + na.z * na.z) * tanTheta; + na.y = Math.sqrt(na.x * na.x + na.z * na.z) * tanTheta; na.normalize(); - nb[1] = Math.sqrt(nb.x * nb.x + nb.z * nb.z) * tanTheta; - na.normalize(); - - for (y = 0; y < segmentsY; y++) { + nb.y = Math.sqrt(nb.x * nb.x + nb.z * nb.z) * tanTheta; + nb.normalize(); + for (var y = 0; y < heightSegments; y++) { var v1 = vertices[y][x]; var v2 = vertices[y + 1][x]; var v3 = vertices[y + 1][x + 1]; var v4 = vertices[y][x + 1]; - + var n1 = na.clone(); var n2 = na.clone(); var n3 = nb.clone(); @@ -86,68 +90,58 @@ class CylinderGeometry extends Geometry { var uv3 = uvs[y + 1][x + 1].clone(); var uv4 = uvs[y][x + 1].clone(); - this.faces.add(new Face4(v1, v2, v3, v4, [n1, n2, n3, n4])); - this.faceVertexUvs[0].add([uv1, uv2, uv3, uv4]); + faces.add(new Face3(v1, v2, v4, [n1, n2, n4])); + faceVertexUvs[0].add([uv1, uv2, uv4]); + faces.add(new Face3(v2, v3, v4, [n2.clone(), n3, n4.clone()])); + faceVertexUvs[0].add([uv2.clone(), uv3, uv4.clone()]); } - } // top cap - if (!openEnded && radiusTop > 0) { - this.vertices.add(new Vector3(0.0, heightHalf, 0.0)); - - for (x = 0; x < segmentsX; x++) { - + + for (var x = 0; x < radialSegments; x++) { var v1 = vertices[0][x]; var v2 = vertices[0][x + 1]; var v3 = this.vertices.length - 1; - + var n1 = new Vector3(0.0, 1.0, 0.0); var n2 = new Vector3(0.0, 1.0, 0.0); var n3 = new Vector3(0.0, 1.0, 0.0); var uv1 = uvs[0][x].clone(); var uv2 = uvs[0][x + 1].clone(); - var uv3 = new UV(uv2.u, 0.0); + var uv3 = new Vector2(uv2.x, 0.0); this.faces.add(new Face3(v1, v2, v3, [n1, n2, n3])); this.faceVertexUvs[0].add([uv1, uv2, uv3]); - } - } // bottom cap - if (!openEnded && radiusBottom > 0) { - this.vertices.add(new Vector3(0.0, -heightHalf, 0.0)); - for (x = 0; x < segmentsX; x++) { - - var v1 = vertices[y][x + 1]; - var v2 = vertices[y][x]; + for (var x = 0; x < radialSegments; x++) { + var v1 = vertices[heightSegments][x + 1]; + var v2 = vertices[heightSegments][x]; var v3 = this.vertices.length - 1; - + var n1 = new Vector3(0.0, -1.0, 0.0); var n2 = new Vector3(0.0, -1.0, 0.0); var n3 = new Vector3(0.0, -1.0, 0.0); - var uv1 = uvs[y][x + 1].clone(); - var uv2 = uvs[y][x].clone(); - var uv3 = new UV(uv2.u, 1.0); - - this.faces.add(new Face3(v1, v2, v3, [n1, n2, n3])); - this.faceVertexUvs[0].add([uv1, uv2, uv3]); + var uv1 = uvs[heightSegments][x + 1].clone(); + var uv2 = uvs[heightSegments][x].clone(); + var uv3 = new Vector2(uv2.x, 1.0); + faces.add(new Face3(v1, v2, v3, [n1, n2, n3])); + faceVertexUvs[0].add([uv1, uv2, uv3]); } - } - this.computeCentroids(); - this.computeFaceNormals(); + computeFaceNormals(); } } diff --git a/lib/extras/geometries/extrude_geometry.dart b/lib/extras/geometries/extrude_geometry.dart index 0cf703c6..f71733fd 100644 --- a/lib/extras/geometries/extrude_geometry.dart +++ b/lib/extras/geometries/extrude_geometry.dart @@ -30,241 +30,147 @@ part of three; **/ class ExtrudeGeometry extends Geometry { + String type = 'ExtrudeGeometry'; + List shapes; - List shapes; - - var shapebb; - - ExtrudeGeometry(this.shapes, {amount: 100, bevelThickness: 6.0, bevelSize: null, bevelSegments: 3, bevelEnabled: true, - curveSegments: 12, steps: 1, //can assume a number of steps or a List with all U's of steps - bendPath, extrudePath, frames, material, extrudeMaterial}) : super() { + ExtrudeGeometry(shapes, {int curveSegments: 12, int steps: 1, int amount: 100, bool bevelEnabled: true, + double bevelThickness: 6.0, double bevelSize, int bevelSegments: 3, + Curve extrudePath, TubeGeometryFrenetFrames frames, int material, int extrudeMaterial, ExtrudeGeometryWorldUVGenerator uvGenerator}) : super() { if (bevelSize == null) bevelSize = bevelThickness - 2.0; if (shapes == null) { - shapes = []; + this.shapes = []; return; } - - shapebb = shapes.last.getBoundingBox(); - - addShapeList( - shapes, - amount, - bevelThickness, - bevelSize, - bevelSegments, - bevelEnabled, - curveSegments, - steps, - bendPath, - extrudePath, - frames, - material, - extrudeMaterial); + + this.shapes = shapes is! List ? [shapes] : shapes; + + addShapeList(this.shapes, curveSegments, steps, amount, bevelEnabled, bevelThickness, bevelSize, bevelSegments, + extrudePath, frames, material, extrudeMaterial, uvGenerator); computeCentroids(); computeFaceNormals(); - - // can't really use automatic vertex normals - // as then front and back sides get smoothed too - // should do separate smoothing just for sides - - //this.computeVertexNormals(); - - //console.log( "took", ( Date.now() - startTime ) ); - } - - - addShapeList(List shapes, num amount, num bevelThickness, double bevelSize, int bevelSegments, bool bevelEnabled, - curveSegments, steps, bendPath, Curve extrudePath, TubeGeometry frames, int material, int extrudeMaterial) { + void addShapeList(shapes, curveSegments, steps, amount, bevelEnabled, bevelThickness, bevelSize, bevelSegments, + extrudePath, frames, material, extrudeMaterial, uvGenerator) { var sl = shapes.length; for (var s = 0; s < sl; s++) { var shape = shapes[s]; - addShape( - shape, - amount, - bevelThickness, - bevelSize, - bevelSegments, - bevelEnabled, - curveSegments, - steps, - bendPath, - extrudePath, - frames, - material, - extrudeMaterial); + addShape(shape, curveSegments, steps, amount, bevelEnabled, bevelThickness, bevelSize, bevelSegments, + extrudePath, frames, material, extrudeMaterial, uvGenerator); } } // addShape Helpers - _scalePt2(Vector2 pt, Vector2 vec, num size) { - if (vec == null) print("die"); + Vector2 _scalePt2(Vector2 pt, Vector2 vec, num size) { + if (vec == null) print("THREE.ExtrudeGeometry: vec does not exist"); return vec.clone().scale(size).add(pt); } - _getBevelVec2(Vector2 pt_i, Vector2 pt_j, Vector2 pt_k) { - - var a = ExtrudeGeometry.__v1, - b = ExtrudeGeometry.__v2, - v_hat = ExtrudeGeometry.__v3, - w_hat = ExtrudeGeometry.__v4, - p = ExtrudeGeometry.__v5, - q = ExtrudeGeometry.__v6, - v, - w, - v_dot_w_hat, - q_sub_p_dot_w_hat, - s, - intersection; - - // good reading for line-line intersection - // http://sputsoft.com/blog/2010/03/line-line-intersection.html - - // define a as vector j->i - // define b as vectot k->i - - a.setValues(pt_i.x - pt_j.x, pt_i.y - pt_j.y); - b.setValues(pt_i.x - pt_k.x, pt_i.y - pt_k.y); - - // get unit vectors - - v = a.normalize(); - w = b.normalize(); - - // normals from pt i - - v_hat.setValues(-v.y, v.x); - w_hat.setValues(w.y, -w.x); - - // pts from i - - p.setFrom(pt_i).add(v_hat); - q.setFrom(pt_i).add(w_hat); - - if (p.x == q.x && p.y == q.y) { // TODO add vector_math ".equals(p, q)" - - //console.log("Warning: lines are straight"); - return w_hat.clone(); - - } - - // Points from j, k. helps prevents points cross overover most of the time - - p.setFrom(pt_j).add(v_hat); - q.setFrom(pt_k).add(w_hat); - - v_dot_w_hat = v.dot(w_hat); - q_sub_p_dot_w_hat = q.sub(p).dot(w_hat); - - // We should not reach these conditions - - if (v_dot_w_hat == 0) { - - print("Either infinite or no solutions!"); - - if (q_sub_p_dot_w_hat == 0) { - - print("Its finite solutions."); - + Vector2 _getBevelVec(Vector2 inPt, Vector2 inPrev, Vector2 inNext) { + var EPSILON = 0.0000000001; + + // computes for inPt the corresponding point inPt' on a new contour + // shiftet by 1 unit (length of normalized vector) to the left + // if we walk along contour clockwise, this new contour is outside the old one + // + // inPt' is the intersection of the two lines parallel to the two + // adjacent edges of inPt at a distance of 1 unit on the left side. + + var v_trans_x, v_trans_y, shrink_by = 1; // resulting translation vector for inPt + + // good reading for geometry algorithms (here: line-line intersection) + // http://geomalgorithms.com/a05-_intersect-1.html + + var v_prev_x = inPt.x - inPrev.x, v_prev_y = inPt.y - inPrev.y; + var v_next_x = inNext.x - inPt.x, v_next_y = inNext.y - inPt.y; + + var v_prev_lensq = (v_prev_x * v_prev_x + v_prev_y * v_prev_y); + + // check for colinear edges + var colinear0 = (v_prev_x * v_next_y - v_prev_y * v_next_x); + + if (colinear0.abs() > EPSILON) { // not colinear + + // length of vectors for normalizing + + var v_prev_len = Math.sqrt(v_prev_lensq); + var v_next_len = Math.sqrt(v_next_x * v_next_x + v_next_y * v_next_y); + + // shift adjacent points by unit vectors to the left + + var ptPrevShift_x = (inPrev.x - v_prev_y / v_prev_len); + var ptPrevShift_y = (inPrev.y + v_prev_x / v_prev_len); + + var ptNextShift_x = (inNext.x - v_next_y / v_next_len); + var ptNextShift_y = (inNext.y + v_next_x / v_next_len); + + // scaling factor for v_prev to intersection point + + var sf = ((ptNextShift_x - ptPrevShift_x) * v_next_y - + (ptNextShift_y - ptPrevShift_y) * v_next_x ) / + (v_prev_x * v_next_y - v_prev_y * v_next_x); + + // vector from inPt to intersection point + + v_trans_x = (ptPrevShift_x + v_prev_x * sf - inPt.x); + v_trans_y = (ptPrevShift_y + v_prev_y * sf - inPt.y); + + // Don't normalize!, otherwise sharp corners become ugly + // but prevent crazy spikes + var v_trans_lensq = (v_trans_x * v_trans_x + v_trans_y * v_trans_y); + if (v_trans_lensq <= 2) { + return new Vector2(v_trans_x, v_trans_y); } else { - - print("Too bad, no solutions."); - + shrink_by = Math.sqrt(v_trans_lensq / 2); + } + } else { // handle special case of colinear edges + var direction_eq = false; // assumes: opposite + if (v_prev_x > EPSILON) { + if (v_next_x > EPSILON) { direction_eq = true; } + } else { + if (v_prev_x < -EPSILON) { + if (v_next_x < -EPSILON) { direction_eq = true; } + } else { + if (v_prev_y.sign == v_next_y.sign) { direction_eq = true; } + } } + if (direction_eq) { + // console.log("Warning: lines are a straight sequence"); + v_trans_x = - v_prev_y; + v_trans_y = v_prev_x; + shrink_by = Math.sqrt(v_prev_lensq); + } else { + // console.log("Warning: lines are a straight spike"); + v_trans_x = v_prev_x; + v_trans_y = v_prev_y; + shrink_by = Math.sqrt(v_prev_lensq / 2); + } } - s = q_sub_p_dot_w_hat / v_dot_w_hat; - - if (s < 0) { - - // in case of emergecy, revert to algorithm 1. - - return _getBevelVec1(pt_i, pt_j, pt_k); - - } - - intersection = v.scale(s).add(p); - - return intersection.sub(pt_i).clone(); // Don't normalize!, otherwise sharp corners become ugly - - } - - - static var RAD_TO_DEGREES = 180 / Math.PI; - - -// Algorithm 2 - _getBevelVec(pt_i, pt_j, pt_k) => _getBevelVec2(pt_i, pt_j, pt_k); - - _getBevelVec1(pt_i, pt_j, pt_k) { - - var anglea = Math.atan2(pt_j.y - pt_i.y, pt_j.x - pt_i.x); - var angleb = Math.atan2(pt_k.y - pt_i.y, pt_k.x - pt_i.x); - - if (anglea > angleb) { - - angleb += Math.PI * 2; - - } - - var anglec = (anglea + angleb) / 2; - var x = -Math.cos(anglec); - var y = -Math.sin(anglec); - - var vec = new Vector2(x, y); //.normalize(); - - return vec; - + return new Vector2(v_trans_x / shrink_by, v_trans_y / shrink_by); } _v(x, y, z) { vertices.add(new Vector3(x, y, z)); } - - // TODO - This is a helper function to reverse a list added by nelsonsilva - List _reverse(List list) { - List reversed = []; - var i = list.length; - while (i > 0) { - reversed.add(list[--i]); - } - return reversed; - } - - addShape(Shape shape, num amount, num bevelThickness, double bevelSize, int bevelSegments, bool bevelEnabled, - curveSegments, steps, bendPath, Curve extrudePath, TubeGeometry frames, int material, int extrudeMaterial, - {ExtrudeGeometryWorldUVGenerator UVGenerator}) { - - + void addShape(Shape shape, curveSegments, steps, amount, bevelEnabled, bevelThickness, bevelSize, bevelSegments, + extrudePath, frames, material, extrudeMaterial, uvGenerator) { var extrudePts, extrudeByPath = false; - //shapebb = shape.getBoundingBox(); - // set UV generator - var uvgen = (UVGenerator != null) ? UVGenerator : new ExtrudeGeometryWorldUVGenerator(); + var uvgen = uvGenerator != null ? uvGenerator : new ExtrudeGeometryWorldUVGenerator(); - TubeGeometry splineTube; - Vector3 binormal, normal, position2; - - var nSteps = (steps is List) ? steps.length : steps; + TubeGeometryFrenetFrames splineTube; if (extrudePath != null) { - - if (steps is List) { - List divisions = [0]; - divisions.addAll(steps); - extrudePts = extrudePath.getUPoints(divisions); - } else { - extrudePts = extrudePath.getSpacedPoints(steps); - } + extrudePts = extrudePath.getSpacedPoints( steps ); extrudeByPath = true; bevelEnabled = false; // bevels not supported for path extrusion @@ -273,39 +179,23 @@ class ExtrudeGeometry extends Geometry { // Reuse TNB from TubeGeomtry for now. // TODO1 - have a .isClosed in spline? - splineTube = (frames != null) ? frames : new TubeGeometry.FrenetFrames(extrudePath, steps, false); - binormal = new Vector3.zero(); - normal = new Vector3.zero(); - position2 = new Vector3.zero(); + splineTube = frames != null ? frames : new TubeGeometryFrenetFrames(extrudePath, steps, false); } // Safeguards if bevels are not enabled if (!bevelEnabled) { - bevelSegments = 0; bevelThickness = 0.0; bevelSize = 0.0; - } // Variables initalization - - List ahole; - var h, hl; // looping of holes - - var bevelPoints = []; - + var shapesOffset = this.vertices.length; - if (bendPath != null) { - - shape.addWrapPath(bendPath); - - } - - var shapePoints = shape.extractPoints(); + var shapePoints = shape.extractPoints(curveSegments); List vertices = shapePoints["shape"]; List> holes = shapePoints["holes"]; @@ -313,34 +203,25 @@ class ExtrudeGeometry extends Geometry { var reverse = !ShapeUtils.isClockWise(vertices); if (reverse) { - - vertices = _reverse(vertices); + vertices = vertices.reversed.toList(); // Maybe we should also check if holes are in the opposite direction, just to be safe ... - for (h = 0; h < holes.length; h++) { - - ahole = holes[h]; + for (var h = 0; h < holes.length; h++) { + var ahole = holes[h]; if (ShapeUtils.isClockWise(ahole)) { - - holes[h] = _reverse(ahole); - + holes[h] = ahole.reversed.toList(); } - } reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)! - } - - var faces = ShapeUtils.triangulateShape(vertices, holes); - //var faces = THREE.Shape.Utils.triangulate2( vertices, holes ); - + // Would it be better to move points after triangulation? - // shapePoints = shape.extractAllPointsWithBend( curveSegments, bendPath ); + // shapePoints = shape.extractAllPointsWithBend(curveSegments, bendPath); // vertices = shapePoints.shape; // holes = shapePoints.holes; @@ -352,246 +233,158 @@ class ExtrudeGeometry extends Geometry { var contour = vertices; // vertices has all points but contour has only points of circumference - for (h = 0; h < holes.length; h++) { - - ahole = holes[h]; + for (var h = 0; h < holes.length; h++) { + var ahole = holes[h]; vertices = new List.from(vertices); vertices.addAll(ahole); - } - - var b, - bs, - t, - z, - vert, - vlen = vertices.length, - face, - flen = faces.length, - cont, - clen = contour.length; - + var vlen = vertices.length, + flen = faces.length; //------ // Find directions for point movement // + var contourMovements = []; - - var contourMovements = new List(contour.length); - - num i = 0, - il = contour.length, - j = il - 1, - k = i + 1; - for (i = 0; i < il; i++) { - + for (var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) { if (j == il) j = 0; if (k == il) k = 0; // (j)---(i)---(k) // console.log('i,j,k', i, j , k) - var pt_i = contour[i]; - var pt_j = contour[j]; - var pt_k = contour[k]; - - contourMovements[i] = _getBevelVec(contour[i], contour[j], contour[k]); - j++; - k++; + contourMovements.add(_getBevelVec(contour[i], contour[j], contour[k])); } - List holesMovements = [], - oneHoleMovements, + var holesMovements = [], verticesMovements = new List.from(contourMovements); - for (h = 0; h < holes.length; h++) { - - ahole = holes[h]; - - oneHoleMovements = new List(ahole.length); - - i = 0; - il = ahole.length; - j = il - 1; - k = i + 1; + for (var h = 0, hl = holes.length; h < hl; h ++) { + var ahole = holes[h]; - for (i = 0; i < il; i++) { + var oneHoleMovements = []; + for (var i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++) { if (j == il) j = 0; if (k == il) k = 0; // (j)---(i)---(k) - oneHoleMovements[i] = _getBevelVec(ahole[i], ahole[j], ahole[k]); - j++; - k++; + oneHoleMovements.add(_getBevelVec(ahole[i], ahole[j], ahole[k])); } holesMovements.add(oneHoleMovements); verticesMovements.addAll(oneHoleMovements); - } - // Loop bevelSegments, 1 for the front, 1 for the back - for (b = 0; b < bevelSegments; b++) { - //for ( b = bevelSegments; b > 0; b -- ) { - - t = b / bevelSegments; - z = bevelThickness * (1 - t); + for (var b = 0; b < bevelSegments; b++) { + var t = b / bevelSegments; + var z = bevelThickness * (1 - t); - //z = bevelThickness * t; - bs = bevelSize * (Math.sin(t * Math.PI / 2)); // curved - //bs = bevelSize * t ; // linear + var bs = bevelSize * (Math.sin(t * Math.PI / 2)); // curved // contract shape - for (i = 0; i < contour.length; i++) { - - vert = _scalePt2(contour[i], contourMovements[i], bs); - //vert = scalePt( contour[ i ], contourCentroid, bs, false ); + for (var i = 0; i < contour.length; i++) { + var vert = _scalePt2(contour[i], contourMovements[i], bs); _v(vert.x, vert.y, -z); - } // expand holes - for (h = 0; h < holes.length; h++) { - - ahole = holes[h]; - oneHoleMovements = holesMovements[h]; - - for (i = 0; i < ahole.length; i++) { - - vert = _scalePt2(ahole[i], oneHoleMovements[i], bs); - //vert = scalePt( ahole[ i ], holesCentroids[ h ], bs, true ); + for (var h = 0; h < holes.length; h++) { + var ahole = holes[h]; + var oneHoleMovements = holesMovements[h]; + for (var i = 0; i < ahole.length; i++) { + var vert = _scalePt2(ahole[i], oneHoleMovements[i], bs); _v(vert.x, vert.y, -z); - } - } - } - - bs = bevelSize; + var bs = bevelSize; // Back facing vertices - for (i = 0; i < vlen; i++) { - - vert = bevelEnabled ? _scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i]; + for (var i = 0; i < vlen; i++) { + var vert = bevelEnabled ? _scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i]; if (!extrudeByPath) { - _v(vert.x, vert.y, 0.0); - } else { + var normal = new Vector3.copy(splineTube.normals[0])..scale(vert.x); + var binormal = new Vector3.copy(splineTube.binormals[0])..scale(vert.y); - // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); - - normal.setFrom(splineTube.normals[0]).scale(vert.x); - binormal.setFrom(splineTube.binormals[0]).scale(vert.y); - - position2.setFrom(extrudePts[0]).add(normal).add(binormal); + var position2 = new Vector3.copy(extrudePts[0])..add(normal)..add(binormal); _v(position2.x, position2.y, position2.z); - } - } // Add stepped vertices... // Including front facing vertices - var s; - - for (s = 1; s <= nSteps; s++) { - - for (i = 0; i < vlen; i++) { - - vert = bevelEnabled ? _scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i]; + for (var s = 1; s <= steps; s++) { + for (var i = 0; i < vlen; i++) { + var vert = bevelEnabled ? _scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i]; if (!extrudeByPath) { - - _v(vert.x, vert.y, amount / nSteps * s); - + _v(vert.x, vert.y, amount / steps * s); } else { + var normal = new Vector3.copy(splineTube.normals[s])..scale(vert.x); + var binormal = new Vector3.copy(splineTube.binormals[s])..scale(vert.y); - // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); - - normal.setFrom(splineTube.normals[s]).scale(vert.x); - binormal.setFrom(splineTube.binormals[s]).scale(vert.y); - - position2.setFrom(extrudePts[s]).add(normal).add(binormal); + var position2 = new Vector3.copy(extrudePts[s])..add(normal)..add(binormal); _v(position2.x, position2.y, position2.z); - } - } - } - // Add bevel segments planes - //for ( b = 1; b <= bevelSegments; b ++ ) { - for (b = bevelSegments - 1; b >= 0; b--) { - - t = b / bevelSegments; - z = bevelThickness * (1 - t); - //bs = bevelSize * ( 1-Math.sin ( ( 1 - t ) * Math.PI/2 ) ); + for (var b = bevelSegments - 1; b >= 0; b--) { + var t = b / bevelSegments; + var z = bevelThickness * (1 - t); bs = bevelSize * Math.sin(t * Math.PI / 2); // contract shape - for (i = 0; i < contour.length; i++) { - - vert = _scalePt2(contour[i], contourMovements[i], bs); + for (var i = 0; i < contour.length; i++) { + var vert = _scalePt2(contour[i], contourMovements[i], bs); _v(vert.x, vert.y, amount + z); - } // expand holes - for (h = 0; h < holes.length; h++) { - - ahole = holes[h]; - oneHoleMovements = holesMovements[h]; - - for (i = 0; i < ahole.length; i++) { + for (var h = 0; h < holes.length; h++) { + var ahole = holes[h]; + var oneHoleMovements = holesMovements[h]; - vert = _scalePt2(ahole[i], oneHoleMovements[i], bs); + for (var i = 0; i < ahole.length; i++) { + var vert = _scalePt2(ahole[i], oneHoleMovements[i], bs); if (!extrudeByPath) { - _v(vert.x, vert.y, amount + z); - } else { - - _v(vert.x, vert.y + extrudePts[nSteps - 1].y, extrudePts[nSteps - 1].x + z); - + _v(vert.x, vert.y + extrudePts[steps - 1].y, extrudePts[steps - 1].x + z); } - } - } - } - //// /// Handle Faces //// ///// Internal functions - f3(a, b, c, isBottom) { + f3(a, b, c) { a += shapesOffset; b += shapesOffset; c += shapesOffset; @@ -599,8 +392,7 @@ class ExtrudeGeometry extends Geometry { // normal, color, material this.faces.add(new Face3(a, b, c, null, null, material)); - var uvs = - isBottom ? uvgen.generateBottomUV(this, shape, null, a, b, c) : uvgen.generateTopUV(this, shape, null, a, b, c); + var uvs = uvgen.generateTopUV(this, a, b, c); this.faceVertexUvs[0].add(uvs); } @@ -611,67 +403,63 @@ class ExtrudeGeometry extends Geometry { c += shapesOffset; d += shapesOffset; - this.faces.add(new Face4(a, b, c, d, null, null, extrudeMaterial)); + this.faces.add(new Face3(a, b, d, null, null, extrudeMaterial)); + this.faces.add(new Face3(b, c, d, null, null, extrudeMaterial)); - var uvs = uvgen.generateSideWallUV(this, shape, wallContour, null, a, b, c, d, stepIndex, stepsLength); - this.faceVertexUvs[0].add(uvs); + var uvs = uvgen.generateSideWallUV(this, a, b, c, d); + + this.faceVertexUvs[0].add([uvs[0], uvs[1], uvs[3]]); + this.faceVertexUvs[0].add([uvs[1], uvs[2], uvs[3]]); } // Top and bottom faces //buildLidFaces() { if (bevelEnabled) { - var layer = 0; // steps + 1 var offset = vlen * layer; // Bottom faces - for (i = 0; i < flen; i++) { - - face = faces[i]; - f3(face[2] + offset, face[1] + offset, face[0] + offset, true); - + for (var i = 0; i < flen; i++) { + var face = faces[i]; + f3(face[2] + offset, face[1] + offset, face[0] + offset); } - layer = nSteps + bevelSegments * 2; + layer = steps + bevelSegments * 2; offset = vlen * layer; // Top faces - for (i = 0; i < flen; i++) { - face = faces[i]; - f3(face[0] + offset, face[1] + offset, face[2] + offset, false); + for (var i = 0; i < flen; i++) { + var face = faces[i]; + f3(face[0] + offset, face[1] + offset, face[2] + offset); } } else { - // Bottom faces - - for (i = 0; i < flen; i++) { - face = faces[i]; - f3(face[2], face[1], face[0], true); + for (var i = 0; i < flen; i++) { + var face = faces[i]; + f3(face[2], face[1], face[0]); } // Top faces - - for (i = 0; i < flen; i++) { - face = faces[i]; - f3(face[0] + vlen * nSteps, face[1] + vlen * nSteps, face[2] + vlen * nSteps, false); + for (var i = 0; i < flen; i++) { + var face = faces[i]; + f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps); } } - sidewalls(List contour, int layeroffset) { - var i, j, k; - i = contour.length; + void sidewalls(List contour, int layeroffset) { + var i = contour.length; while (--i >= 0) { - j = i; - k = i - 1; + var j = i; + var k = i - 1; if (k < 0) k = contour.length - 1; //console.log('b', i,j, i-1, k,vertices.length); var s = 0, - sl = nSteps + bevelSegments * 2; + sl = steps + bevelSegments * 2; for (s = 0; s < sl; s++) { var slen1 = vlen * s; @@ -693,70 +481,53 @@ class ExtrudeGeometry extends Geometry { sidewalls(contour, layeroffset); layeroffset += contour.length; - for (h = 0; h < holes.length; h++) { - ahole = holes[h]; + for (var h = 0; h < holes.length; h++) { + var ahole = holes[h]; sidewalls(ahole, layeroffset); //, true layeroffset += ahole.length; } } - - - static Vector2 ___v1 = null; - static get __v1 => (___v1 == null) ? ___v1 = new Vector2.zero() : ___v1; - static Vector2 ___v2 = null; - static get __v2 => (___v2 == null) ? ___v2 = new Vector2.zero() : ___v2; - static Vector2 ___v3 = null; - static get __v3 => (___v3 == null) ? ___v3 = new Vector2.zero() : ___v3; - static Vector2 ___v4 = null; - static get __v4 => (___v4 == null) ? ___v4 = new Vector2.zero() : ___v4; - static Vector2 ___v5 = null; - static get __v5 => (___v5 == null) ? ___v5 = new Vector2.zero() : ___v5; - static Vector2 ___v6 = null; - static get __v6 => (___v6 == null) ? ___v6 = new Vector2.zero() : ___v6; } class ExtrudeGeometryWorldUVGenerator { - List generateTopUV(Geometry geometry, extrudedShape, extrudeOptions, int indexA, int indexB, int indexC) { - var ax = geometry.vertices[indexA].x, - ay = geometry.vertices[indexA].y, - - bx = geometry.vertices[indexB].x, - by = geometry.vertices[indexB].y, - - cx = geometry.vertices[indexC].x, - cy = geometry.vertices[indexC].y; - - return [new UV(ax, 1 - ay), new UV(bx, 1 - by), new UV(cx, 1 - cy)]; - } - - List generateBottomUV(Geometry geometry, extrudedShape, extrudeOptions, int indexA, int indexB, int indexC) { - return generateTopUV(geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC); + List generateTopUV(Geometry geometry, int indexA, int indexB, int indexC) { + var vertices = geometry.vertices; + + var a = vertices[indexA]; + var b = vertices[indexB]; + var c = vertices[indexC]; + + return [ + new Vector2(a.x, a.y), + new Vector2(b.x, b.y), + new Vector2(c.x, c.y) + ]; } - List generateSideWallUV(Geometry geometry, extrudedShape, wallContour, extrudeOptions, int indexA, int indexB, - int indexC, int indexD, stepIndex, stepsLength) { - var ax = geometry.vertices[indexA].x, - ay = geometry.vertices[indexA].y, - az = geometry.vertices[indexA].z, - - bx = geometry.vertices[indexB].x, - by = geometry.vertices[indexB].y, - bz = geometry.vertices[indexB].z, - - cx = geometry.vertices[indexC].x, - cy = geometry.vertices[indexC].y, - cz = geometry.vertices[indexC].z, - - dx = geometry.vertices[indexD].x, - dy = geometry.vertices[indexD].y, - dz = geometry.vertices[indexD].z; - - if ((ay - by).abs() < 0.01) { - return [new UV(ax, az), new UV(bx, bz), new UV(cx, cz), new UV(dx, dz)]; + List generateSideWallUV(Geometry geometry, int indexA, int indexB, int indexC, int indexD) { + var vertices = geometry.vertices; + + var a = vertices[indexA]; + var b = vertices[indexB]; + var c = vertices[indexC]; + var d = vertices[indexD]; + + if ((a.y - b.y).abs() < 0.01) { + return [ + new Vector2(a.x, 1 - a.z), + new Vector2(b.x, 1 - b.z), + new Vector2(c.x, 1 - c.z), + new Vector2(d.x, 1 - d.z) + ]; } else { - return [new UV(ay, az), new UV(by, bz), new UV(cy, cz), new UV(dy, dz)]; + return [ + new Vector2(a.y, 1 - a.z), + new Vector2(b.y, 1 - b.z), + new Vector2(c.y, 1 - c.z), + new Vector2(d.y, 1 - d.z) + ]; } } } diff --git a/lib/extras/geometries/icosahedron_geometry.dart b/lib/extras/geometries/icosahedron_geometry.dart index 817c9c43..64747ba6 100644 --- a/lib/extras/geometries/icosahedron_geometry.dart +++ b/lib/extras/geometries/icosahedron_geometry.dart @@ -6,40 +6,16 @@ class IcosahedronGeometry extends PolyhedronGeometry { var t = (1 + Math.sqrt(5)) / 2; var vertices = [ - [-1, t, 0], - [1, t, 0], - [-1, -t, 0], - [1, -t, 0], - [0, -1, t], - [0, 1, t], - [0, -1, -t], - [0, 1, -t], - [t, 0, -1], - [t, 0, 1], - [-t, 0, -1], - [-t, 0, 1]]; + [-1, t, 0], [1, t, 0], [-1, -t, 0], [1, -t, 0], [0, -1, t], [0, 1, t], + [0, -1, -t], [0, 1, -t], [t, 0, -1], [t, 0, 1], [-t, 0, -1], [-t, 0, 1] + ]; var faces = [ - [0, 11, 5], - [0, 5, 1], - [0, 1, 7], - [0, 7, 10], - [0, 10, 11], - [1, 5, 9], - [5, 11, 4], - [11, 10, 2], - [10, 7, 6], - [7, 1, 8], - [3, 9, 4], - [3, 4, 2], - [3, 2, 6], - [3, 6, 8], - [3, 8, 9], - [4, 9, 5], - [2, 4, 11], - [6, 2, 10], - [8, 6, 7], - [9, 8, 1]]; + [0, 11, 5], [0, 5, 1], [0, 1, 7], [0, 7, 10], [0, 10, 11], [1, 5, 9], + [5, 11, 4], [11, 10, 2], [10, 7, 6], [7, 1, 8], [3, 9, 4], [3, 4, 2], + [3, 2, 6], [3, 6, 8], [3, 8, 9], [4, 9, 5], [2, 4, 11], [6, 2, 10], + [8, 6, 7], [9, 8, 1] + ]; return new IcosahedronGeometry._internal(vertices, faces, radius, detail); } diff --git a/lib/extras/geometries/lathe_geometry.dart b/lib/extras/geometries/lathe_geometry.dart index d5a1205e..8d3f9150 100644 --- a/lib/extras/geometries/lathe_geometry.dart +++ b/lib/extras/geometries/lathe_geometry.dart @@ -1,54 +1,60 @@ +/* + * @author astrodud / http://astrodud.isgreat.org/ + * @author zz85 / https://github.com/zz85 + * @author bhouston / http://exocortex.com + * + * based on r66 + */ + part of three; +/// Class for generating meshes with axial symmetry. Possible uses include donuts, +/// pipes, vases etc. The lathe rotate around the Z axis. class LatheGeometry extends Geometry { - - int steps; - num angle; - - LatheGeometry(List points, [this.steps = 12, this.angle = 2 * Math.PI]) : super() { - - var newV = points.map((pt) => pt.clone()).toList(); - vertices.addAll(newV); - - Matrix4 matrix = new Matrix4.rotationZ(angle / steps); - - var i, - il = steps + 1; - - for (i = 0; i < il; i++) { - - for (var j = 0; j < newV.length; j++) { - newV[j].applyProjection(matrix); - vertices.add(newV[j]); - } - + /// Creates a new lathe geometry based on the following parameters: + /// + /// * [points]: List of [Vector3]. Since this rotates around Z axis, the y-values can be set to 0 + /// * [segments]: The number of circumference segments to generate. + /// * [phiStart]: The starting angle in radians. + /// * [phiLength]: The radian (0 to 2PI) range of the lathed section 2PI is a closed lathe, less than 2PI is a portion. + LatheGeometry(List points, [int segments = 12, double phiStart = 0.0, double phiLength = 2 * Math.PI]) : super() { + var inversePointLength = 1.0 / (points.length - 1); + var inverseSegments = 1.0 / segments; + + for (var i = 0; i <= segments; i++) { + var phi = phiStart + i * inverseSegments * phiLength; + + var c = Math.cos(phi), + s = Math.sin(phi); + + points.forEach((pt) => vertices.add(new Vector3(c * pt.x - s * pt.y, s * pt.x + c * pt.y, pt.z))); } - for (i = 0; i < steps; i++) { - - for (var k = 0, - kl = points.length; k < kl - 1; k++) { + var np = points.length; - var a = i * kl + k; - var b = ((i + 1) % il) * kl + k; - var c = ((i + 1) % il) * kl + (k + 1) % kl; - var d = i * kl + (k + 1) % kl; + for (var i = 0; i < segments; i++) { + for ( var j = 0; j < points.length - 1; j++ ) { + var base = j + np * i; + var a = base; + var b = base + np; + var c = base + 1 + np; + var d = base + 1; - this.faces.add(new Face4(a, b, c, d)); + var u0 = i * inverseSegments; + var v0 = j * inversePointLength; + var u1 = u0 + inverseSegments; + var v1 = v0 + inversePointLength; - this.faceVertexUvs[0].add( - [ - new UV(1 - i / steps, k / kl), - new UV(1 - (i + 1) / steps, k / kl), - new UV(1 - (i + 1) / steps, (k + 1) / kl), - new UV(1 - i / steps, (k + 1) / kl)]); + faces.add(new Face3(a, b, d)); + faceVertexUvs[0].add([new Vector2(u0, v0), new Vector2(u1, v0), new Vector2(u0, v1)]); + faces.add(new Face3(b, c, d)); + faceVertexUvs[0].add([new Vector2(u1, v0), new Vector2(u1, v1), new Vector2(u0, v1)]); } - } - computeCentroids(); + mergeVertices(); computeFaceNormals(); computeVertexNormals(); } -} +} \ No newline at end of file diff --git a/lib/extras/geometries/parametric_geometry.dart b/lib/extras/geometries/parametric_geometry.dart index f10fb36b..8691ca83 100644 --- a/lib/extras/geometries/parametric_geometry.dart +++ b/lib/extras/geometries/parametric_geometry.dart @@ -1,86 +1,192 @@ -part of three; - -/** +/* * @author zz85 / https://github.com/zz85 - * Parametric Surfaces Geometry - * based on the brilliant article by @prideout http://prideout.net/blog/?p=44 - * - * new THREE.ParametricGeometry( parametricFunction, uSegments, ySegements, useTris ); - * + * Parametric Surfaces Geometry based on the brilliant article by @prideout http://prideout.net/blog/?p=44 + * + * based on r66 */ -class ParametricGeometry extends Geometry { - - ParametricGeometry(Vector3 func(num u, num v), int slices, int stacks, [bool useTris = false]) : super() { - var verts = this.vertices; - var faces = this.faces; - var uvs = this.faceVertexUvs[0]; +part of three; - var i, il, j, p; - var u, v; +class ParametricGeometry extends Geometry { + ParametricGeometry(Function func, int slices, int stacks) : super() { + var uvs = faceVertexUvs[0]; - var stackCount = stacks + 1; var sliceCount = slices + 1; - for (i = 0; i <= stacks; i++) { - - v = i / stacks; - - for (j = 0; j <= slices; j++) { + for (var i = 0; i <= stacks; i++) { + var v = i / stacks; - u = j / slices; - - p = func(u, v); - verts.add(p); + for (var j = 0; j <= slices; j++) { + var u = j / slices; + var p = func(u, v); + vertices.add(p); } } - var a, b, c, d; - var uva, uvb, uvc, uvd; - - for (i = 0; i < stacks; i++) { - - for (j = 0; j < slices; j++) { - - a = i * sliceCount + j; - b = i * sliceCount + j + 1; - c = (i + 1) * sliceCount + j; - d = (i + 1) * sliceCount + j + 1; - - uva = new UV(j / slices, i / stacks); - uvb = new UV((j + 1) / slices, i / stacks); - uvc = new UV(j / slices, (i + 1) / stacks); - uvd = new UV((j + 1) / slices, (i + 1) / stacks); - - if (useTris) { - - faces.add(new Face3(a, b, c)); - faces.add(new Face3(b, d, c)); + for (var i = 0; i < stacks; i ++) { + for (var j = 0; j < slices; j ++) { + var a = i * sliceCount + j; + var b = i * sliceCount + j + 1; + var c = (i + 1) * sliceCount + j + 1; + var d = (i + 1) * sliceCount + j; - uvs.add([uva, uvb, uvc]); - uvs.add([uvb, uvd, uvc]); + var uva = new Vector2(j / slices, i / stacks); + var uvb = new Vector2((j + 1) / slices, i / stacks); + var uvc = new Vector2((j + 1) / slices, (i + 1) / stacks); + var uvd = new Vector2(j / slices, (i + 1) / stacks); - } else { - - faces.add(new Face4(a, b, d, c)); - uvs.add([uva, uvb, uvd, uvc]); - - } + faces.add(new Face3(a, b, d)); + uvs.add([uva, uvb, uvd]); + faces.add(new Face3(b, c, d)); + uvs.add([uvb.clone(), uvc, uvd.clone()]); } - } - // console.log(this); - - // magic bullet - // var diff = this.mergeVertices(); - // console.log('removed ', diff, ' vertices by merging'); - - computeCentroids(); computeFaceNormals(); computeVertexNormals(); + } + + factory ParametricGeometry.klein(int slices, int stacks) { + var func = (v, u) { + u *= Math.PI; + v *= 2 * Math.PI; + + u = u * 2; + var x, y, z; + if (u < Math.PI) { + x = 3 * Math.cos(u) * (1 + Math.sin(u)) + (2 * (1 - Math.cos(u) / 2)) * Math.cos(u) * Math.cos(v); + z = -8 * Math.sin(u) - 2 * (1 - Math.cos(u) / 2) * Math.sin(u) * Math.cos(v); + } else { + x = 3 * Math.cos(u) * (1 + Math.sin(u)) + (2 * (1 - Math.cos(u) / 2)) * Math.cos(v + Math.PI); + z = -8 * Math.sin(u); + } + + y = -2 * (1 - Math.cos(u) / 2) * Math.sin(v); + return new Vector3(x, y, z); + }; + + return new ParametricGeometry(func, slices, stacks); + } + + /// Parametric Replacement for PlaneGeometry. + factory ParametricGeometry.plane(double width, double height, int slices, int stacks) { + return new ParametricGeometry((u, v) => new Vector3(u * width, 0.0, v * height), slices, stacks); + } + + factory ParametricGeometry.mobius(int slices, int stacks) { + var func = (u, t) { + u = u - 0.5; + var v = 2 * Math.PI * t; + + var x, y, z; + + var a = 2; + x = Math.cos(v) * (a + u * Math.cos(v/2)); + y = Math.sin(v) * (a + u * Math.cos(v/2)); + z = u * Math.sin(v/2); + return new Vector3(x, y, z); + }; + + return new ParametricGeometry(func, slices, stacks); + } + + factory ParametricGeometry.mobius3d(int slices, int stacks) { + var func = (u, t) { + u *= Math.PI; + t *= 2 * Math.PI; + + u = u * 2; + var phi = u / 2; + var major = 2.25, a = 0.125, b = 0.65; + var x, y, z; + x = a * Math.cos(t) * Math.cos(phi) - b * Math.sin(t) * Math.sin(phi); + z = a * Math.cos(t) * Math.sin(phi) + b * Math.sin(t) * Math.cos(phi); + y = (major + x) * Math.sin(u); + x = (major + x) * Math.cos(u); + return new Vector3(x, y, z); + }; + + return new ParametricGeometry(func, slices, stacks); + } + + /// Parametric Replacement for SphereGeometry + factory ParametricGeometry.sphere(double size, int u, int v) { + var sphere = (u, v) { + u *= Math.PI; + v *= 2 * Math.PI; + + var x = size * Math.sin(u) * Math.cos(v); + var y = size * Math.sin(u) * Math.sin(v); + var z = size * Math.cos(u); + + + return new Vector3(x, y, z); + }; + + return new ParametricGeometry(sphere, u, v); + } + + /// Parametric Replacement for TubeGeometry. + factory ParametricGeometry.tube(path, + {int segments: 64, + double radius: 1.0, + int segmentsRadius: 8, + bool closed: false, + bool debug: false}) { + var frames = new TubeGeometryFrenetFrames(path, segments, closed); + + var func = (u, v) { + v *= 2 * Math.PI; + + var i = (u * segments).floor(); + + var pos = path.getPointAt(u); + + var tangent = frames.tangents[i]; + var normal = frames.normals[i]; + var binormal = frames.binormals[i]; + + //if (debug) { + // debugObject.add(new ArrowHelper(tangent, pos, radius, 0x0000ff)); + // debugObject.add(new ArrowHelper(normal, pos, radius, 0xff0000)); + // debugObject.add(new ArrowHelper(binormal, pos, radius, 0x00ff00)); + //} + + var cx = -radius * Math.cos(v); + var cy = radius * Math.sin(v); + + var pos2 = pos.clone(); + pos2.x += cx * normal.x + cy * binormal.x; + pos2.y += cx * normal.y + cy * binormal.y; + pos2.z += cx * normal.z + cy * binormal.z; + + return pos2.clone(); + }; + + return new ParametricGeometry(func, segments, segmentsRadius); + } + + /// Parametric Replacement for TorusKnotGeometry. + factory ParametricGeometry.torusKnot({double radius: 200.0, + double tube: 40.0, + int segmentsR: 64, + int segmentsT: 8, + double p: 2.0, + double q: 3.0, + double heightScale: 1.0}) { + var path = new Curve.create((double t) { + t *= Math.PI * 2; + var r = 0.5; + var tx = (1 + r * Math.cos(q * t)) * Math.cos(p * t), + ty = (1 + r * Math.cos(q * t)) * Math.sin(p * t), + tz = r * Math.sin(q * t); + + return new Vector3(tx, ty * heightScale, tz)..scale(radius); + }); + + return new ParametricGeometry.tube(path, segments: segmentsR, radius: tube, segmentsRadius: segmentsT, closed: true); } -} +} \ No newline at end of file diff --git a/lib/extras/geometries/plane_geometry.dart b/lib/extras/geometries/plane_geometry.dart index 0932deb5..5404710a 100644 --- a/lib/extras/geometries/plane_geometry.dart +++ b/lib/extras/geometries/plane_geometry.dart @@ -1,62 +1,67 @@ -part of three; - -/** +/* * @author mr.doob / http://mrdoob.com/ * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as * * Ported to Dart from JS by: * @author rob silverton / http://www.unwrong.com/ + * + * based on r66 */ +part of three; + +/** + * A class for generating plane geometries. + * + * var geometry = new PlaneGeometry(5.0, 20.0); + * var material = new MeshBasicMaterial(color: 0xffff00, side: DOUBLE_SIDE); + * var plane = new Mesh(geometry, material); + * scene.add(plane); + */ class PlaneGeometry extends Geometry { + /// Creates a new plane geometry. + PlaneGeometry(double width, double height, [int widthSegments = 1, int heightSegments = 1]) : super() { + var width_half = width / 2; + var height_half = height / 2; + + var gridX = widthSegments; + var gridZ = heightSegments; - PlaneGeometry(double width, double height, [int segmentsWidth, int segmentsHeight]) : super() { - //THREE.Geometry.call( this ); + var gridX1 = gridX + 1; + var gridZ1 = gridZ + 1; - double width_half = width / 2; - double height_half = height / 2; - int gridX = segmentsWidth != null ? segmentsWidth : 1; - int gridY = segmentsHeight != null ? segmentsHeight : 1; - int gridX1 = gridX + 1; - int gridY1 = gridY + 1; - double segment_width = width / gridX; - double segment_height = height / gridY; - Vector3 normal = new Vector3(0.0, 0.0, 1.0); + var segment_width = width / gridX; + var segment_height = height / gridZ; - for (int iy = 0; iy < gridY1; iy++) { - for (int ix = 0; ix < gridX1; ix++) { - num x = ix * segment_width - width_half; - num y = iy * segment_height - height_half; + var normal = new Vector3(0.0, -1.0, 0.0); + + for (var iz = 0; iz < gridZ1; iz++) { + for (var ix = 0; ix < gridX1; ix++) { + var x = ix * segment_width - width_half; + var y = iz * segment_height - height_half; vertices.add(new Vector3(x, -y, 0.0)); } } - for (int iy = 0; iy < gridY; iy++) { - for (int ix = 0; ix < gridX; ix++) { - num a = ix + gridX1 * iy; - num b = ix + gridX1 * (iy + 1); - num c = (ix + 1) + gridX1 * (iy + 1); - num d = (ix + 1) + gridX1 * iy; - - Face4 face = new Face4(a, b, c, d); - face.normal = normal.clone(); - face.vertexNormals.addAll([normal.clone(), normal.clone(), normal.clone(), normal.clone()]); - - faces.add(face); - - List faceVertexUV = faceVertexUvs[0]; - List newUVs = new List(); - newUVs.addAll( - [ - new UV(ix / gridX, iy / gridY), - new UV(ix / gridX, (iy + 1) / gridY), - new UV((ix + 1) / gridX, (iy + 1) / gridY), - new UV((ix + 1) / gridX, iy / gridY)]); - faceVertexUV.add(newUVs); + for (var iz = 0; iz < gridZ; iz++) { + for (var ix = 0; ix < gridX; ix++) { + var a = ix + gridX1 * iz; + var b = ix + gridX1 * (iz + 1); + var c = (ix + 1) + gridX1 * (iz + 1); + var d = (ix + 1) + gridX1 * iz; + + var uva = new Vector2(ix / gridX, 1 - iz / gridZ); + var uvb = new Vector2(ix / gridX, 1 - (iz + 1) / gridZ); + var uvc = new Vector2((ix + 1) / gridX, 1 - (iz + 1) / gridZ); + var uvd = new Vector2((ix + 1) / gridX, 1 - iz / gridZ); + + faces.add(new Face3(a, b, d, [normal.clone(), normal.clone(), normal.clone()])); + faceVertexUvs[0].add([uva, uvb, uvd]); + + faces.add(new Face3(b, c, d, [normal.clone(), normal.clone(), normal.clone()])); + faceVertexUvs[0].add([uvb.clone(), uvc, uvd.clone()]); } } - - computeCentroids(); } -} +} \ No newline at end of file diff --git a/lib/extras/geometries/polyhedron_geometry.dart b/lib/extras/geometries/polyhedron_geometry.dart index 2da9f351..8ae7d13a 100644 --- a/lib/extras/geometries/polyhedron_geometry.dart +++ b/lib/extras/geometries/polyhedron_geometry.dart @@ -1,7 +1,6 @@ part of three; class PolyhedronGeometry extends Geometry { - List _midpoints; // nelsonsilva - We're using a PolyhedronGeometryVertex decorator to allow adding index and uv properties @@ -9,7 +8,6 @@ class PolyhedronGeometry extends Geometry { PolyhedronGeometry(List> lvertices, List> lfaces, [double radius = 1.0, num detail = 0]) : super() { - _midpoints = []; lvertices.forEach((vertex) { @@ -30,12 +28,10 @@ class PolyhedronGeometry extends Geometry { computeCentroids(); boundingSphere = new BoundingSphere(radius: radius); - } // Project vector onto sphere's surface PolyhedronGeometryVertex _prepare(PolyhedronGeometryVertex vertex) { - vertex.normalize(); _p.add(vertex); vertex.index = _p.length - 1; @@ -44,19 +40,14 @@ class PolyhedronGeometry extends Geometry { var u = _azimuth(vertex) / 2 / Math.PI + 0.5; var v = _inclination(vertex) / Math.PI + 0.5; - vertex.uv = new UV(u, 1 - v); + vertex.uv = new Vector2(u, 1 - v); return vertex; - } - // Approximate a curved face with recursively sub-divided triangles. - _make(PolyhedronGeometryVertex v1, PolyhedronGeometryVertex v2, PolyhedronGeometryVertex v3, num detail) { - if (detail < 1) { - var face = new Face3(v1.index, v2.index, v3.index, [v1.clone(), v2.clone(), v3.clone()]); face.centroid.add(v1).add(v2).add(v3).scale(1.0 / 3.0); face.normal = face.centroid.clone().normalize(); @@ -64,9 +55,7 @@ class PolyhedronGeometry extends Geometry { var azi = _azimuth(face.centroid); this.faceVertexUvs[0].add([_correctUV(v1.uv, v1, azi), _correctUV(v2.uv, v2, azi), _correctUV(v3.uv, v3, azi)]); - } else { - detail -= 1; // split triangle into 4 smaller triangles @@ -75,13 +64,10 @@ class PolyhedronGeometry extends Geometry { _make(_midpoint(v1, v2), v2, _midpoint(v2, v3), detail); // left quadrant _make(_midpoint(v1, v3), _midpoint(v2, v3), v3, detail); // right quadrant _make(_midpoint(v1, v2), _midpoint(v2, v3), _midpoint(v1, v3), detail); // center quadrant - } - } _midpoint(v1, v2) { - // TODO - nelsonsilva - refactor this code // arrays don't "automagically" grow in Dart! if (_midpoints.length < v1.index + 1) { @@ -122,7 +108,6 @@ class PolyhedronGeometry extends Geometry { } return mid; - } /// Angle around the Y axis, counter-clockwise when looking from above. @@ -133,11 +118,10 @@ class PolyhedronGeometry extends Geometry { Math.atan2(-vector.y, Math.sqrt((vector.x * vector.x) + (vector.z * vector.z))); /// Texture fixing helper. Spheres have some odd behaviours. - UV _correctUV(UV uv, Vector3 vector, double azimuth) { - if ((azimuth < 0) && (uv.u == 1)) uv = new UV(uv.u - 1, uv.v); - if ((vector.x == 0) && (vector.z == 0)) uv = new UV(azimuth / 2 / Math.PI + 0.5, uv.v); + Vector2 _correctUV(Vector2 uv, Vector3 vector, double azimuth) { + if ((azimuth < 0) && (uv.x == 1)) uv = new Vector2(uv.x - 1, uv.y); + if ((vector.x == 0) && (vector.z == 0)) uv = new Vector2(azimuth / 2 / Math.PI + 0.5, uv.y); return uv; - } } @@ -146,8 +130,8 @@ class PolyhedronGeometry extends Geometry { * */ class PolyhedronGeometryVertex extends Vector3 { int index; - UV uv; + Vector2 uv; PolyhedronGeometryVertex([num x = 0.0, num y = 0.0, num z = 0.0]) : super(x.toDouble(), y.toDouble(), z.toDouble()); PolyhedronGeometryVertex.fromVector3(Vector3 other) : super.copy(other); -} +} \ No newline at end of file diff --git a/lib/extras/geometries/ring_geometry.dart b/lib/extras/geometries/ring_geometry.dart new file mode 100644 index 00000000..f81241f4 --- /dev/null +++ b/lib/extras/geometries/ring_geometry.dart @@ -0,0 +1,72 @@ +/* + * @author Kaleb Murphy + * + * based on r66 + */ + +part of three; + +/** + * A class for generating a two-dimensional ring geometry. + * + * var geometry = new RingGeometry(1.0, 5.0, 32); + * var material = new MeshBasicMaterial(color: 0xffff00, side: DOUBLE_SIDE); + * var mesh = new Mesh(geometry, material); + * scene.add(mesh); + */ +class RingGeometry extends Geometry { + RingGeometry([double innerRadius = 0.0, + double outerRadius = 50.0, + int thetaSegments, + int phiSegments, + double thetaStart = 0.0, + double thetaLength = Math.PI * 2]) : super() { + thetaSegments = thetaSegments != null ? Math.max(3, thetaSegments) : 8; + phiSegments = phiSegments != null ? Math.max(3, phiSegments) : 8; + + List uvs = []; + double radius = innerRadius; + double radiusStep = ((outerRadius - innerRadius) / phiSegments); + + for (var i = 0; i <= phiSegments; i++) { // concentric circles inside ring + for (var o = 0; o <= thetaSegments; o++) { // number of segments per circle + var vertex = new Vector3.zero(); + var segment = thetaStart + o / thetaSegments * thetaLength; + + vertex.x = radius * Math.cos(segment); + vertex.y = radius * Math.sin(segment); + + vertices.add(vertex); + uvs.add(new Vector2((vertex.x / outerRadius + 1) / 2, (vertex.y / outerRadius + 1) / 2)); + } + + radius += radiusStep; + } + + for (var i = 0; i < phiSegments; i++) { // concentric circles inside ring + var thetaSegment = i * thetaSegments; + + for (var o = 0; o <= thetaSegments; o++) { // number of segments per circle + var segment = o + thetaSegment; + + var v1 = segment + i; + var v2 = segment + thetaSegments + i; + var v3 = segment + thetaSegments + 1 + i; + + faces.add(new Face3(v1, v2, v3, [new Vector3(0.0, -1.0, 0.0), new Vector3(0.0, -1.0, 0.0), new Vector3(0.0, -1.0, 0.0)])); + faceVertexUvs[0].add([uvs[v1].clone(), uvs[v2].clone(), uvs[v3].clone()]); + + v1 = segment + i; + v2 = segment + thetaSegments + 1 + i; + v3 = segment + 1 + i; + + faces.add(new Face3(v1, v2, v3, [new Vector3(0.0, -1.0, 0.0), new Vector3(0.0, -1.0, 0.0), new Vector3(0.0, -1.0, 0.0)])); + faceVertexUvs[0].add([uvs[v1].clone(), uvs[v2].clone(), uvs[v3].clone()]); + } + } + + computeFaceNormals(); + + boundingSphere = new BoundingSphere(radius: radius); + } +} \ No newline at end of file diff --git a/lib/extras/geometries/shape_geometry.dart b/lib/extras/geometries/shape_geometry.dart index cc9ffb9a..05fbd108 100644 --- a/lib/extras/geometries/shape_geometry.dart +++ b/lib/extras/geometries/shape_geometry.dart @@ -17,122 +17,95 @@ part of three; **/ class ShapeGeometry extends Geometry { - + String type = 'ShapeGeometry'; + List shapes; - var shapebb; - - ShapeGeometry(this.shapes, {int curveSegments: 12, int material, ExtrudeGeometryWorldUVGenerator UVGenerator}) + ShapeGeometry(shapes, {int curveSegments: 12, int material, ExtrudeGeometryWorldUVGenerator uvGenerator}) : super() { if (shapes == null) { - shapes = []; + this.shapes = []; return; } + + this.shapes = shapes is! List ? [shapes] : shapes; - shapebb = shapes.last.getBoundingBox(); - - addShapeList(shapes, curveSegments, material, UVGenerator); + addShapeList(this.shapes, curveSegments, material, uvGenerator); computeCentroids(); computeFaceNormals(); - } - - - addShapeList(List shapes, num curveSegments, int material, [ExtrudeGeometryWorldUVGenerator UVGenerator = - null]) { + void addShapeList(List shapes, num curveSegments, int material, [ExtrudeGeometryWorldUVGenerator uvGenerator]) { var sl = shapes.length; for (var s = 0; s < sl; s++) { var shape = shapes[s]; - addShape(shape, curveSegments, material, UVGenerator); + addShape(shape, curveSegments, material, uvGenerator); } } - addShape(Shape shape, num curveSegments, int material, [ExtrudeGeometryWorldUVGenerator UVGenerator = null]) { + void addShape(Shape shape, num curveSegments, int material, [ExtrudeGeometryWorldUVGenerator uvGenerator]) { + curveSegments = curveSegments != null ? curveSegments : 12; + var uvgen = uvGenerator == null ? new ExtrudeGeometryWorldUVGenerator() : uvGenerator; - // set UV generator - var uvgen = (UVGenerator != null) ? UVGenerator : new ExtrudeGeometryWorldUVGenerator(); - - var i, hole, s; + // var shapesOffset = this.vertices.length; var shapePoints = shape.extractPoints(curveSegments); - List vertices = shapePoints["shape"]; - List> holes = shapePoints["holes"]; + var vertices = shapePoints['shape']; + var holes = shapePoints['holes']; var reverse = !ShapeUtils.isClockWise(vertices); if (reverse) { - vertices = vertices.reversed.toList(); // Maybe we should also check if holes are in the opposite direction, just to be safe... - for (i = 0; i < holes.length; i++) { - - hole = holes[i]; + for (var i = 0, l = holes.length; i < l; i ++) { + var hole = holes[i]; if (ShapeUtils.isClockWise(hole)) { - holes[i] = hole.reversed.toList(); - } - } reverse = false; - } var faces = ShapeUtils.triangulateShape(vertices, holes); // Vertices - var contour = vertices; - - for (i = 0; i < holes.length; i++) { - - hole = holes[i]; - - vertices = new List.from(vertices); + for (var i = 0, l = holes.length; i < l; i ++) { + var hole = holes[i]; vertices.addAll(hole); - } // - var vert, - vlen = vertices.length; - var face, - flen = faces.length; - var cont, - clen = contour.length; + var vlen = vertices.length; + var flen = faces.length; - for (i = 0; i < vlen; i++) { - - vert = vertices[i]; - - this.vertices.add(new Vector3((vert.x).toDouble(), (vert.y).toDouble(), 0.0)); + for (var i = 0; i < vlen; i ++) { + var vert = vertices[i]; + this.vertices.add(new Vector3(vert.x, vert.y, 0.0)); } - for (i = 0; i < flen; i++) { - - face = faces[i]; - + for (var i = 0; i < flen; i ++) { + var face = faces[i]; + var a = face[0] + shapesOffset; var b = face[1] + shapesOffset; var c = face[2] + shapesOffset; this.faces.add(new Face3(a, b, c, null, null, material)); - faceVertexUvs[0].add(uvgen.generateBottomUV(this, shape, null, a, b, c)); - + this.faceVertexUvs[0].add(uvgen.generateTopUV(this, a, b, c)); } } } - diff --git a/lib/extras/geometries/sphere_geometry.dart b/lib/extras/geometries/sphere_geometry.dart index 3e3b0ed6..54b45079 100644 --- a/lib/extras/geometries/sphere_geometry.dart +++ b/lib/extras/geometries/sphere_geometry.dart @@ -1,90 +1,94 @@ +/* + * @author mrdoob / http://mrdoob.com/ + * + * based on r66 + */ + part of three; +/** + * A class for generating sphere geometries. + * + * var geometry = new SphereGeometry(5.0, 32, 32); + * var material = new MeshBasicMaterial(color: 0xffff00); + * var sphere = new Mesh(geometry, material); + * scene.add(sphere); + */ class SphereGeometry extends Geometry { - double radius; - - SphereGeometry([this.radius = 50.0, int segmentsWidth = 8, int segmentsHeight = 6, double phiStart = 0.0, - double phiLength = Math.PI * - 2.0, double thetaStart = 0.0, double thetaLength = Math.PI]) : super() { - - int segmentsX = Math.max(3, segmentsWidth); - int segmentsY = Math.max(2, segmentsHeight); - - List vertices = [], - uvs = []; - - for (int y = 0; y <= segmentsY; y++) { - - var verticesRow = []; - var uvsRow = []; - - for (int x = 0; x <= segmentsX; x++) { - - double u = x.toDouble() / segmentsX.toDouble(); - double v = y.toDouble() / segmentsY.toDouble(); - - Vector3 vertex = new Vector3.zero(); - vertex.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); - vertex.y = radius * Math.cos(thetaStart + v * thetaLength); - vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); - - this.vertices.add(vertex); - - verticesRow.add(this.vertices.length - 1); - uvsRow.add(new UV(u, 1 - v)); - + /// Creates a new sphere geometry. + SphereGeometry([double radius = 50.0, + int widthSegments, + int heightSegments, + double phiStart = 0.0, + double phiLength = Math.PI * 2.0, + double thetaStart = 0.0, + double thetaLength = Math.PI]) { + widthSegments = widthSegments != null ? Math.max(3, widthSegments) : 8; + heightSegments = heightSegments != null ? Math.max(2, heightSegments) : 6; + + List> _vertices = []; + List> uvs = []; + + for (var y = 0; y <= heightSegments; y++) { + List verticesRow = []; + List uvsRow = []; + + for (var x = 0; x <= widthSegments; x++) { + var u = x / widthSegments; + var v = y / heightSegments; + + var vertex = new Vector3.zero() + ..x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength) + ..y = radius * Math.cos(thetaStart + v * thetaLength) + ..z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); + + vertices.add(vertex); + + verticesRow.add(vertices.length - 1); + uvsRow.add(new Vector2(u, 1 - v)); } - vertices.add(verticesRow); + _vertices.add(verticesRow); uvs.add(uvsRow); - } - for (int y = 0; y < segmentsY; y++) { - - for (int x = 0; x < segmentsX; x++) { - - var v1 = vertices[y][x + 1]; - var v2 = vertices[y][x]; - var v3 = vertices[y + 1][x]; - var v4 = vertices[y + 1][x + 1]; - - var n1 = this.vertices[v1].clone().normalize(); - var n2 = this.vertices[v2].clone().normalize(); - var n3 = this.vertices[v3].clone().normalize(); - var n4 = this.vertices[v4].clone().normalize(); - - var uv1 = uvs[y][x + 1].clone(); - var uv2 = uvs[y][x].clone(); - var uv3 = uvs[y + 1][x].clone(); + for (var y = 0; y < heightSegments; y++) { + for (var x = 0; x < widthSegments; x++) { + var v1 = _vertices[y][x + 1]; + var v2 = _vertices[y][x]; + var v3 = _vertices[y + 1][x]; + var v4 = _vertices[y + 1][x + 1]; + + var n1 = vertices[v1].clone().normalize(); + var n2 = vertices[v2].clone().normalize(); + var n3 = vertices[v3].clone().normalize(); + var n4 = vertices[v4].clone().normalize(); + + var uv1 = uvs[y ][x + 1].clone(); + var uv2 = uvs[y ][x ].clone(); + var uv3 = uvs[y + 1][x ].clone(); var uv4 = uvs[y + 1][x + 1].clone(); - if (this.vertices[v1].y.abs() == radius) { - - this.faces.add(new Face3(v1, v3, v4, [n1, n3, n4])); - this.faceVertexUvs[0].add([uv1, uv3, uv4]); - - } else if (this.vertices[v3].y.abs() == radius) { - - this.faces.add(new Face3(v1, v2, v3, [n1, n2, n3])); - this.faceVertexUvs[0].add([uv1, uv2, uv3]); - + if (vertices[v1].y.abs() == radius) { + uv1.x = (uv1.x + uv2.x) / 2; + faces.add(new Face3(v1, v3, v4, [n1, n3, n4])); + faceVertexUvs[0].add([uv1, uv3, uv4]); + } else if (vertices[v3].y.abs() == radius) { + uv3.x = (uv3.x + uv4.x) / 2; + faces.add(new Face3(v1, v2, v3, [n1, n2, n3])); + faceVertexUvs[0].add([uv1, uv2, uv3]); } else { + faces.add(new Face3(v1, v2, v4, [n1, n2, n4])); + faceVertexUvs[0].add([uv1, uv2, uv4]); - this.faces.add(new Face4(v1, v2, v3, v4, [n1, n2, n3, n4])); - this.faceVertexUvs[0].add([uv1, uv2, uv3, uv4]); - + faces.add(new Face3(v2, v3, v4, [n2.clone(), n3, n4.clone()])); + faceVertexUvs[0].add([uv2.clone(), uv3, uv4.clone()]); } - } - } - this.computeCentroids(); - this.computeFaceNormals(); - - this.boundingSphere = new BoundingSphere(radius: radius); + computeFaceNormals(); + boundingSphere = new BoundingSphere(radius: radius); } - } diff --git a/lib/extras/geometries/text_geometry.dart b/lib/extras/geometries/text_geometry.dart index 4f891e8f..7ce3049f 100644 --- a/lib/extras/geometries/text_geometry.dart +++ b/lib/extras/geometries/text_geometry.dart @@ -3,8 +3,8 @@ part of three; class TextGeometry extends ExtrudeGeometry { factory TextGeometry(String text, [num height = 50, // height <=> amount, bool bend = false, // ExtrudeGeometry parameters - int bevelThickness = 10, num bevelSize = 8, int bevelSegments = 3, bool bevelEnabled = false, int curveSegments = 12, - int steps = 1, bendPath, extrudePath, int material, int extrudeMaterial, // FontUtils.generateShapes parameters + double bevelThickness = 10.0, num bevelSize = 8, int bevelSegments = 3, bool bevelEnabled = false, int curveSegments = 12, + int steps = 1, extrudePath, int material, int extrudeMaterial, // FontUtils.generateShapes parameters int size = 100, String font = "helvetiker", String weight = "normal", String style = "normal"]) { var textShapes = FontUtils.generateShapes(text, size, curveSegments, font, weight, style); @@ -45,7 +45,6 @@ class TextGeometry extends ExtrudeGeometry { bevelEnabled: bevelEnabled, curveSegments: curveSegments, steps: steps, - bendPath: bendPath, extrudePath: extrudePath, material: material, extrudeMaterial: extrudeMaterial); diff --git a/lib/extras/geometries/torus_geometry.dart b/lib/extras/geometries/torus_geometry.dart index 10c20290..72e39b75 100644 --- a/lib/extras/geometries/torus_geometry.dart +++ b/lib/extras/geometries/torus_geometry.dart @@ -1,63 +1,68 @@ +/* + * @author oosmoxiecode + * @author mrdoob / http://mrdoob.com/ + * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3DLite/src/away3dlite/primitives/Torus.as?r=2888 + * + * based on r66 + */ + part of three; +/** + * A class for generating torus geometries + * + * var geometry = new TorusGeometry(10.0, 3.0, 16, 100); + * var material = new MeshBasicMaterial(color: 0xffff00); + * var torus = new Mesh(geometry, material); + * scene.add(torus); + */ class TorusGeometry extends Geometry { - num radius, tube, segmentsR, segmentsT, arc; - - TorusGeometry([this.radius = 100, this.tube = 40, this.segmentsR = 8, this.segmentsT = 6, this.arc = Math.PI * - 2]) : super() { - - var center = new Vector3.zero(); - var uvs = []; - var normals = []; - - for (var j = 0; j <= this.segmentsR; j++) { - - for (var i = 0; i <= this.segmentsT; i++) { - - var u = i / this.segmentsT * this.arc; - var v = j / this.segmentsR * Math.PI * 2; - - center.x = this.radius * Math.cos(u); - center.y = this.radius * Math.sin(u); - - var vertex = new Vector3.zero(); - vertex.x = (this.radius + this.tube * Math.cos(v)) * Math.cos(u); - vertex.y = (this.radius + this.tube * Math.cos(v)) * Math.sin(u); - vertex.z = this.tube * Math.sin(v); - - this.vertices.add(vertex); - - uvs.add(new UV(i / this.segmentsT, j / this.segmentsR)); - normals.add(vertex.clone().sub(center).normalize()); - + /// Creates a new torus geometry. + TorusGeometry([double radius = 100.0, + double tube = 40.0, + int radialSegments = 8, + int tubularSegments = 6, + double arc = Math.PI * 2]) : super() { + + List uvs = []; + List normals = []; + + for (var j = 0; j <= radialSegments; j++) { + for (var i = 0; i <= tubularSegments; i++) { + var u = i / tubularSegments * arc; + var v = j / radialSegments * Math.PI * 2; + + var center = new Vector3.zero() + ..x = radius * Math.cos(u) + ..y = radius * Math.sin(u); + + var vertex = new Vector3.zero() + ..x = (radius + tube * Math.cos(v)) * Math.cos(u) + ..y = (radius + tube * Math.cos(v)) * Math.sin(u) + ..z = tube * Math.sin(v); + + vertices.add(vertex); + + uvs.add(new Vector2(i / tubularSegments, j / radialSegments)); + normals.add((vertex - center).normalize()); } } + for (var j = 1; j <= radialSegments; j++) { + for (var i = 1; i <= tubularSegments; i++) { + var a = (tubularSegments + 1) * j + i - 1; + var b = (tubularSegments + 1) * (j - 1) + i - 1; + var c = (tubularSegments + 1) * (j - 1) + i; + var d = (tubularSegments + 1) * j + i; - for (var j = 1; j <= this.segmentsR; j++) { - - for (var i = 1; i <= this.segmentsT; i++) { - - var a = (this.segmentsT + 1) * j + i - 1; - var b = (this.segmentsT + 1) * (j - 1) + i - 1; - var c = (this.segmentsT + 1) * (j - 1) + i; - var d = (this.segmentsT + 1) * j + i; + faces.add(new Face3(a, b, d, [normals[a].clone(), normals[b].clone(), normals[d].clone()])); + faceVertexUvs[0].add([uvs[a].clone(), uvs[b].clone(), uvs[d].clone()]); - var face = new Face4(a, b, c, d, [normals[a], normals[b], normals[c], normals[d]]); - face.normal.add(normals[a]); - face.normal.add(normals[b]); - face.normal.add(normals[c]); - face.normal.add(normals[d]); - face.normal.normalize(); - - this.faces.add(face); - - this.faceVertexUvs[0].add([uvs[a].clone(), uvs[b].clone(), uvs[c].clone(), uvs[d].clone()]); + faces.add(new Face3(b, c, d, [normals[b].clone(), normals[c].clone(), normals[d].clone()])); + faceVertexUvs[0].add([uvs[b].clone(), uvs[c].clone(), uvs[d].clone()]); } - } - this.computeCentroids(); - + computeFaceNormals(); } } diff --git a/lib/extras/geometries/torus_knot_geometry.dart b/lib/extras/geometries/torus_knot_geometry.dart index 5468ac76..dd9f84ac 100644 --- a/lib/extras/geometries/torus_knot_geometry.dart +++ b/lib/extras/geometries/torus_knot_geometry.dart @@ -1,97 +1,91 @@ -part of three; - -/** +/* * @author oosmoxiecode * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473 + * + * based on r66 */ -class TorusKnotGeometry extends Geometry { - - double radius, tube, p, q, heightScale; - num segmentsR, segmentsT; - List grid; - - TorusKnotGeometry([this.radius = 200.0, this.tube = 40.0, this.segmentsR = 64, this.segmentsT = 8, this.p = 2.0, - this.q = 3.0, this.heightScale = 1.0]) - : super() { - - grid = new List(segmentsR); - - var tang = new Vector3.zero(); - var n = new Vector3.zero(); - var bitan = new Vector3.zero(); - - for (var i = 0; i < segmentsR; ++i) { - - this.grid[i] = new List(this.segmentsT); - - for (var j = 0; j < this.segmentsT; ++j) { - - var u = i / this.segmentsR * 2 * this.p * Math.PI; - var v = j / this.segmentsT * 2 * Math.PI; - var p1 = getPos(u, v, this.q, this.p, this.radius, this.heightScale); - var p2 = getPos(u + 0.01, v, this.q, this.p, this.radius, this.heightScale); - var cx, cy; - - tang = p2 - p1; - n = p2 + p1; - - bitan = tang.cross(n); - n = bitan.cross(tang); - bitan.normalize(); - n.normalize(); - - cx = -this.tube * Math.cos(v); // TODO: Hack: Negating it so it faces outside. - cy = this.tube * Math.sin(v); - - p1.x += cx * n.x + cy * bitan.x; - p1.y += cx * n.y + cy * bitan.y; - p1.z += cx * n.z + cy * bitan.z; - - this.grid[i][j] = _vert(p1.x, p1.y, p1.z); +part of three; +/** + * Class for generating torus knot geometries, the particular shape + * of which is defined by a pair of coprime integers, p and q. + * If p and q are not coprime, the result will be a torus link. + * + * var geometry = new TorusKnotGeometry(10.0, 3.0, 100, 16); + * var material = new MeshBasicMaterial(color: 0xffff00); + * var torusKnot = new Mesh(geometry, material); + * scene.add(torusKnot); + * + */ +class TorusKnotGeometry extends Geometry { + List _grid; + + /// Creates a new torus knot geometry. + TorusKnotGeometry([double radius = 100.0, + double tube = 40.0, + int radialSegments = 64, + int tubularSegments = 8, + double p = 2.0, + double q = 3.0, + double heightScale = 1.0]) : super() { + _grid = new List(radialSegments); + + for (var i = 0; i < radialSegments; i++) { + _grid[i] = new List(tubularSegments); + var u = i / radialSegments * 2 * p * Math.PI; + var p1 = _getPos(u, q, p, radius, heightScale); + var p2 = _getPos(u + 0.01, q, p, radius, heightScale); + var tang = p2 - p1; + var n = p2 + p1; + + var bitan = tang.cross(n).normalize(); + n = bitan.cross(tang).normalize(); + + for (var j = 0; j < tubularSegments; j++) { + var v = j / tubularSegments * 2 * Math.PI; + var cx = -tube * Math.cos(v); + var cy = tube * Math.sin(v); + + var pos = new Vector3.zero() + ..x = p1.x + cx * n.x + cy * bitan.x + ..y = p1.y + cx * n.y + cy * bitan.y + ..z = p1.z + cx * n.z + cy * bitan.z; + + vertices.add(pos); + _grid[i][j] = vertices.length - 1; } - } - for (var i = 0; i < this.segmentsR; ++i) { - - for (var j = 0; j < this.segmentsT; ++j) { - - var ip = (i + 1) % this.segmentsR; - var jp = (j + 1) % this.segmentsT; + for (var i = 0; i < radialSegments; ++ i) { + for (var j = 0; j < tubularSegments; ++ j) { + var ip = (i + 1) % radialSegments; + var jp = (j + 1) % tubularSegments; - var a = this.grid[i][j]; - var b = this.grid[ip][j]; - var c = this.grid[ip][jp]; - var d = this.grid[i][jp]; + var a = _grid[i][j]; + var b = _grid[ip][j]; + var c = _grid[ip][jp]; + var d = _grid[i][jp]; - var uva = new UV(i / this.segmentsR, j / this.segmentsT); - var uvb = new UV((i + 1) / this.segmentsR, j / this.segmentsT); - var uvc = new UV((i + 1) / this.segmentsR, (j + 1) / this.segmentsT); - var uvd = new UV(i / this.segmentsR, (j + 1) / this.segmentsT); + var uva = new Vector2(i / radialSegments, j / tubularSegments); + var uvb = new Vector2((i + 1) / radialSegments, j / tubularSegments); + var uvc = new Vector2((i + 1) / radialSegments, (j + 1) / tubularSegments); + var uvd = new Vector2(i / radialSegments, (j + 1) / tubularSegments); - this.faces.add(new Face4(a, b, c, d)); - this.faceVertexUvs[0].add([uva, uvb, uvc, uvd]); + faces.add(new Face3(a, b, d)); + faceVertexUvs[0].add([uva, uvb, uvd]); + faces.add(new Face3(b, c, d)); + faceVertexUvs[0].add([uvb.clone(), uvc, uvd.clone()]); } } - - this.computeCentroids(); - this.computeFaceNormals(); - this.computeVertexNormals(); - - } - - num _vert(double x, double y, double z) { - vertices.add(new Vector3(x, y, z)); - return vertices.length - 1; + + computeFaceNormals(); + computeVertexNormals(); } - - Vector3 getPos(double u, double v, double in_q, double in_p, double radius, double heightScale) { - + + Vector3 _getPos(double u, double in_q, double in_p, double radius, double heightScale) { var cu = Math.cos(u); - var cv = Math.cos(v); var su = Math.sin(u); var quOverP = in_q / in_p * u; var cs = Math.cos(quOverP); @@ -101,6 +95,5 @@ class TorusKnotGeometry extends Geometry { var tz = heightScale * radius * Math.sin(quOverP) * 0.5; return new Vector3(tx, ty, tz); - } } diff --git a/lib/extras/geometries/tube_geometry.dart b/lib/extras/geometries/tube_geometry.dart index 1f318e0e..7724498b 100644 --- a/lib/extras/geometries/tube_geometry.dart +++ b/lib/extras/geometries/tube_geometry.dart @@ -1,244 +1,127 @@ -part of three; - -/** +/* * @author WestLangley / https://github.com/WestLangley * @author zz85 / https://github.com/zz85 * @author miningold / https://github.com/miningold * * Modified from the TorusKnotGeometry by @oosmoxiecode - * - * Creates a tube which extrudes along a 3d spline - * - * Uses parallel transport frames as described in - * http://www.cs.indiana.edu/pub/techreports/TR425.pdf + * + * based on r63 */ -class TubeGeometry extends Geometry { - - var path, segments; - num nSegments, radius, segmentsRadius; - bool closed; - - var grid; - List tangents, normals, binormals; - - Object3D debug; - - TubeGeometry(path, [int segments = 64, this.radius = 1.0, this.segmentsRadius = 8, bool closed = false, bool debug]) - : grid = [], - super() { - - if (debug) this.debug = new Object3D(); - - var tangent, - normal, - binormal, - - numpoints = segments + 1, - - x, - y, - z, - tx, - ty, - tz, - u, - v, - - cx, - cy, - pos, - pos2 = new Vector3.zero(), - i, - j, - ip, - jp, - a, - b, - c, - d, - uva, - uvb, - uvc, - uvd; - - var frames = _frenetFrames(path, segments, closed); - - // consruct the grid - grid.length = numpoints; - - for (i = 0; i < numpoints; i++) { - - grid[i] = new List(this.segmentsRadius); - - u = i / (numpoints - 1); - - pos = path.getPointAt(u); - - tangent = tangents[i]; - normal = normals[i]; - binormal = binormals[i]; - - if (debug) { - - this.debug.add(new ArrowHelper(tangent, pos, radius, 0x0000ff)); - this.debug.add(new ArrowHelper(normal, pos, radius, 0xff0000)); - this.debug.add(new ArrowHelper(binormal, pos, radius, 0x00ff00)); - - } - - for (j = 0; j < this.segmentsRadius; j++) { - - v = j / this.segmentsRadius * 2 * Math.PI; - - cx = -this.radius * Math.cos(v); // TODO: Hack: Negating it so it faces outside. - cy = this.radius * Math.sin(v); +part of three; - pos2.setFrom(pos); +class TubeGeometry extends Geometry { + List tangents; + List normals; + List binormals; + + List grid = []; + + TubeGeometry(Curve path, + [int segments = 64, + double radius = 1.0, + int radialSegments = 8, + bool closed = false]) : super() { + var numpoints = segments + 1; + + var frames = new TubeGeometryFrenetFrames(path, segments, closed); + + tangents = frames.tangents; + normals = frames.normals; + binormals = frames.binormals; + + for (var i = 0; i < numpoints; i++) { + grid.add(new List(radialSegments)); + + var u = i / (numpoints - 1); + + var pos = path.getPointAt(u); + + var normal = normals[i]; + var binormal = binormals[i]; + + for (var j = 0; j < radialSegments; j++) { + var v = j / radialSegments * 2 * Math.PI; + + var cx = -radius * Math.cos(v); + var cy = radius * Math.sin(v); + + var pos2 = new Vector3.copy(pos); pos2.x += cx * normal.x + cy * binormal.x; pos2.y += cx * normal.y + cy * binormal.y; pos2.z += cx * normal.z + cy * binormal.z; - this.grid[i][j] = _vert(pos2.x, pos2.y, pos2.z); - + grid[i][j] = _vert(pos2.x, pos2.y, pos2.z); } } // construct the mesh - - for (i = 0; i < this.nSegments; i++) { - - for (j = 0; j < this.segmentsRadius; j++) { - - ip = (closed) ? (i + 1) % this.nSegments : i + 1; - jp = (j + 1) % this.segmentsRadius; - - a = this.grid[i][j]; // *** NOT NECESSARILY PLANAR ! *** - b = this.grid[ip][j]; - c = this.grid[ip][jp]; - d = this.grid[i][jp]; - - uva = new UV(i / this.nSegments, j / this.segmentsRadius); - uvb = new UV((i + 1) / this.nSegments, j / this.segmentsRadius); - uvc = new UV((i + 1) / this.nSegments, (j + 1) / this.segmentsRadius); - uvd = new UV(i / this.nSegments, (j + 1) / this.segmentsRadius); - - this.faces.add(new Face4(a, b, c, d)); - this.faceVertexUvs[0].add([uva, uvb, uvc, uvd]); - + for (var i = 0; i < segments; i++) { + for (var j = 0; j < radialSegments; j++) { + var ip = closed ? (i + 1) % segments : i + 1; + var jp = (j + 1) % radialSegments; + + var a = grid[i][j]; + var b = grid[ip][j]; + var c = grid[ip][jp]; + var d = grid[i][jp]; + + var uva = new Vector2(i / segments, j / radialSegments); + var uvb = new Vector2((i + 1) / segments, j / radialSegments); + var uvc = new Vector2((i + 1) / segments, (j + 1) / radialSegments); + var uvd = new Vector2(i / segments, (j + 1) / radialSegments); + + faces.add(new Face3(a, b, d)); + faceVertexUvs[0].add([uva, uvb, uvd]); + + faces.add(new Face3(b, c, d)); + faceVertexUvs[0].add([uvb.clone(), uvc, uvd.clone()]); } } - computeCentroids(); computeFaceNormals(); computeVertexNormals(); - } - - int _vert(double x, double y, double z) { + _vert(x, y, z) { vertices.add(new Vector3(x, y, z)); return vertices.length - 1; } +} - - // FrenetFrames - - - TubeGeometry.FrenetFrames(path, segments, closed) { - _frenetFrames(path, segments, closed); - } - -// For computing of Frenet frames, exposing the tangents, normals and binormals the spline - _frenetFrames(ppath, psegments, bool pclosed) { - - this.path = ppath; - this.segments = psegments; - - this.closed = pclosed; - - var tangent = new Vector3.zero(), - normal = new Vector3.zero(), - binormal = new Vector3.zero(), - - mat = new Matrix4.identity(), - theta, - epsilon = 0.0001, - smallest, - - tx, - ty, - tz, - i, - u, - v; - - if (segments is num) { - var length = segments; - segments = []; - for (i = 1; i <= length; i++) { - segments.add(i / (length)); - } - } - this.nSegments = segments.length; - var numpoints = this.nSegments + 1; - - // expose internals - tangents = new List(numpoints); - normals = new List(numpoints); - binormals = new List(numpoints); +class TubeGeometryFrenetFrames { + List tangents; + List normals; + List binormals; + + int nSegments; + + TubeGeometryFrenetFrames(path, int segments, bool closed) { + var EPSILON = 0.0000000001; + + var numpoints = segments + 1; + + normals = new List(numpoints); + binormals = new List(numpoints); // compute the tangent vectors for each segment on the path - - for (i = 0; i < numpoints; i++) { - tangents[i] = (i == 0) ? path.getTangentAt(0) : path.getTangentAt(segments[i - 1]); - tangents[i].normalize(); - } - - _initialNormal1([lastBinormal = null]) { - // fixed start binormal. Has dangers of 0 vectors - if (lastBinormal == null) lastBinormal = new Vector3(0.0, 0.0, 1.0); - normals[0] = lastBinormal.cross(tangents[0]).normalize(); - binormals[0] = tangents[0].cross(normals[0]).normalize(); - } - - _initialNormal2() { - // This uses the Frenet-Serret formula for deriving binormal - var t2 = path.getTangentAt(epsilon); - - normals[0] = (t2 - tangents[0]).normalize(); - binormals[0] = tangents[0].cross(normals[0]); - - normals[0] = binormals[0].cross(tangents[0]).normalize(); // last binormal x tangent - binormals[0] = tangents[0].cross(normals[0]).normalize(); - - } + tangents = new List.generate(numpoints, (i) => path.getTangentAt(i / (numpoints - 1))..normalize()); _initialNormal3() { - // select an initial normal vector perpenicular to the first tangent vector, - // and in the direction of the smallest tangent xyz component - - smallest = double.INFINITY; - tx = (tangents[0].x).abs(); - ty = (tangents[0].y).abs(); - tz = (tangents[0].z).abs(); - - if (tx <= smallest) { - smallest = tx; - normal.setValues(1.0, 0.0, 0.0); - } - - if (ty <= smallest) { - smallest = ty; - normal.setValues(0.0, 1.0, 0.0); - } - - if (tz <= smallest) { - normal.setValues(0.0, 0.0, 1.0); - } - - Vector3 vec = tangents[0].cross(normal).normalize(); + normals[0] = new Vector3.zero(); + binormals[0] = new Vector3.zero(); + var smallest = double.MAX_FINITE; + var tx = tangents[0].x.abs(); + var ty = tangents[0].y.abs(); + var tz = tangents[0].z.abs(); + var normal = new Vector3.zero(); + + if (tx <= smallest) { normal = new Vector3(1.0, 0.0, 0.0); smallest = tx; } + if (ty <= smallest) { normal = new Vector3(0.0, 1.0, 0.0); smallest = ty; } + if (tz <= smallest) { normal = new Vector3(0.0, 0.0, 1.0); } + + var vec = tangents[0].cross(normal).normalize(); normals[0] = tangents[0].cross(vec); binormals[0] = tangents[0].cross(normals[0]); @@ -246,52 +129,37 @@ class TubeGeometry extends Geometry { _initialNormal3(); - // compute the slowly-varying normal and binormal vectors for each segment on the path - - for (i = 1; i < numpoints; i++) { - + for (var i = 1; i < numpoints; i++) { normals[i] = normals[i - 1].clone(); - binormals[i] = binormals[i - 1].clone(); Vector3 vec = tangents[i - 1].cross(tangents[i]); - if (vec.length > epsilon) { - + if (vec.length > EPSILON) { vec.normalize(); - theta = Math.acos(tangents[i - 1].dot(tangents[i])); + var theta = Math.acos(tangents[i - 1].dot(tangents[i])); - normals[i].applyProjection(makeRotationAxis(mat, vec, theta)); + normals[i].applyProjection(new Matrix4.identity().rotate(vec, theta)); } binormals[i] = tangents[i].cross(normals[i]); - } - // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same - if (closed) { - - theta = Math.acos(normals[0].dot(normals[numpoints - 1])); + var theta = Math.acos(normals[0].dot(normals[numpoints - 1])); theta /= (numpoints - 1); if (tangents[0].dot(normals[0].cross(normals[numpoints - 1])) > 0) { - theta = -theta; - } - for (i = 1; i < numpoints; i++) { - - // twist a little... - normals[i].applyProjection(makeRotationAxis(mat, tangents[i], theta * i)); + for (var i = 1; i < numpoints; i++) { + normals[i].applyProjection(new Matrix4.identity().rotate(tangents[i], theta * i)); binormals[i] = tangents[i].cross(normals[i]); - } - } } -} +} \ No newline at end of file diff --git a/lib/extras/geometry_utils.dart b/lib/extras/geometry_utils.dart index 985e74d6..eda20ab3 100644 --- a/lib/extras/geometry_utils.dart +++ b/lib/extras/geometry_utils.dart @@ -38,7 +38,7 @@ Geometry clone(Geometry geometry) { var jl = uv.length; for (var j = 0; j < jl; j++) { - uvCopy.add(new UV(uv[j].u, uv[j].v)); + uvCopy.add(new Vector2(uv[j].u, uv[j].v)); } diff --git a/lib/extras/helpers/axis_helper.dart b/lib/extras/helpers/axis_helper.dart index 82a7879b..85b40f95 100644 --- a/lib/extras/helpers/axis_helper.dart +++ b/lib/extras/helpers/axis_helper.dart @@ -1,44 +1,29 @@ -part of three; - -class AxisHelper extends Object3D { - AxisHelper() { - var lineGeometry = new Geometry(); - lineGeometry.vertices.add(new Vector3.zero()); - lineGeometry.vertices.add(new Vector3(0.0, 100.0, 0.0)); - - var coneGeometry = new CylinderGeometry(0.0, 5.0, 25.0, 5, 1); - - var line, cone; - - // x - - line = new Line(lineGeometry, new LineBasicMaterial(color: 0xff0000)); - line.rotation.z = -Math.PI / 2.0; - this.add(line); +/* + * @author sroucheray / http://sroucheray.org/ + * @author mrdoob / http://mrdoob.com/ + * + * based on r63 + */ - cone = new Mesh(coneGeometry, new MeshBasicMaterial(color: 0xff0000)); - cone.position.x = 100.0; - cone.rotation.z = -Math.PI / 2.0; - this.add(cone); - // y - - line = new Line(lineGeometry, new LineBasicMaterial(color: 0x00ff00)); - this.add(line); - - cone = new Mesh(coneGeometry, new MeshBasicMaterial(color: 0x00ff00)); - cone.position.y = 100.0; - this.add(cone); - - // z - - line = new Line(lineGeometry, new LineBasicMaterial(color: 0x0000ff)); - line.rotation.x = Math.PI / 2.0; - this.add(line); +part of three; - cone = new Mesh(coneGeometry, new MeshBasicMaterial(color: 0x0000ff)); - cone.position.z = 100.0; - cone.rotation.x = Math.PI / 2.0; - this.add(cone); +class AxisHelper extends Line { + factory AxisHelper([double size = 1.0]) { + var geometry = new Geometry() + ..vertices.addAll( + [new Vector3.zero(), new Vector3(size, 0.0, 0.0), + new Vector3.zero(), new Vector3(0.0, size, 0.0), + new Vector3.zero(), new Vector3(0.0, 0.0, size)]) + ..colors.addAll( + [new Color(0xff0000), new Color(0xffaa00), + new Color(0x00ff00), new Color(0xaaff00), + new Color(0x0000ff), new Color(0x00aaff)]); + + var material = new LineBasicMaterial(vertexColors: VertexColors); + + return new AxisHelper._internal(geometry, material, LinePieces); } + + AxisHelper._internal(Geometry geometry, LineBasicMaterial material, int type) : super(geometry, material, type); } diff --git a/lib/extras/renderers/canvas_renderer.dart b/lib/extras/renderers/canvas_renderer.dart index 71caf05a..aac79a33 100644 --- a/lib/extras/renderers/canvas_renderer.dart +++ b/lib/extras/renderers/canvas_renderer.dart @@ -335,42 +335,6 @@ class CanvasRenderer implements Renderer { if (_clipRect.intersects(_bboxRect)) { renderFace3(_v1, _v2, _v3, 0, 1, 2, element, material, scene); } - - } else if (element is RenderableFace4) { - _v1 = element.v1; - _v2 = element.v2; - _v3 = element.v3; - _v4 = element.v4; - - _v1.positionScreen.x *= _canvasWidthHalf; - _v1.positionScreen.y *= _canvasHeightHalf; - _v2.positionScreen.x *= _canvasWidthHalf; - _v2.positionScreen.y *= _canvasHeightHalf; - _v3.positionScreen.x *= _canvasWidthHalf; - _v3.positionScreen.y *= _canvasHeightHalf; - _v4.positionScreen.x *= _canvasWidthHalf; - _v4.positionScreen.y *= _canvasHeightHalf; - - _v5.positionScreen.setFrom(_v2.positionScreen); - _v6.positionScreen.setFrom(_v4.positionScreen); - - if (material.overdraw) { - expand(_v1.positionScreen, _v2.positionScreen); - expand(_v2.positionScreen, _v4.positionScreen); - expand(_v4.positionScreen, _v1.positionScreen); - - expand(_v3.positionScreen, _v5.positionScreen); - expand(_v3.positionScreen, _v6.positionScreen); - } - - _bboxRect.addPoint(_v1.positionScreen.x, _v1.positionScreen.y); - _bboxRect.addPoint(_v2.positionScreen.x, _v2.positionScreen.y); - _bboxRect.addPoint(_v3.positionScreen.x, _v3.positionScreen.y); - _bboxRect.addPoint(_v4.positionScreen.x, _v4.positionScreen.y); - - if (_clipRect.intersects(_bboxRect)) { - renderFace4(_v1, _v2, _v3, _v4, _v5, _v6, element, material, scene); - } } if (debug) { diff --git a/lib/src/core/face4.dart b/lib/src/core/face4.dart deleted file mode 100644 index c99b4239..00000000 --- a/lib/src/core/face4.dart +++ /dev/null @@ -1,31 +0,0 @@ -part of three; - -/// Quadrilateral face. -class Face4 extends Face { - - Face4([int a = 0, int b = 0, int c = 0, int d = 0, normalOrVertexNormals, colorOrVertexColors, int materialIndex]) - : super([a, b, c, d], normalOrVertexNormals, colorOrVertexColors, materialIndex); - - int get a => indices[0]; - set a(int i) { - indices[0] = i; - } - - int get b => indices[1]; - set b(int i) { - indices[1] = i; - } - - int get c => indices[2]; - set c(int i) { - indices[2] = i; - } - - int get d => indices[3]; - set d(int i) { - indices[3] = i; - } - - /// Clone this Face. - clone() => new Face4(a, b, c, d).setFrom(this); -} diff --git a/lib/src/core/geometry.dart b/lib/src/core/geometry.dart index d4f8ad94..fe9c7614 100644 --- a/lib/src/core/geometry.dart +++ b/lib/src/core/geometry.dart @@ -213,7 +213,7 @@ class Geometry extends Object with WebGLGeometry { var f, fl, face; num i, il, vertexIndex, test, w; Vector3 vA, vB, vC; - UV uvA, uvB, uvC; + Vector2 uvA, uvB, uvC; List uv; @@ -246,10 +246,10 @@ class Geometry extends Object with WebGLGeometry { z1 = vB.z - vA.z; z2 = vC.z - vA.z; - s1 = uvB.u - uvA.u; - s2 = uvC.u - uvA.u; - t1 = uvB.v - uvA.v; - t2 = uvC.v - uvA.v; + s1 = uvB.x - uvA.x; + s2 = uvC.x - uvA.x; + t1 = uvB.y - uvA.y; + t2 = uvC.y - uvA.y; r = 1.0 / (s1 * t2 - s2 * t1); sdir.setValues((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); @@ -270,7 +270,7 @@ class Geometry extends Object with WebGLGeometry { for (f = 0; f < fl; f++) { face = this.faces[f]; - UV uv = faceVertexUvs[0][f]; // use UV layer 0 for tangents + Vector2 uv = faceVertexUvs[0][f]; // use UV layer 0 for tangents // TODO - Come up with a way to handle an arbitrary number of vertexes var triangles = []; @@ -375,12 +375,12 @@ class Geometry extends Object with WebGLGeometry { verticesMap[key] = i; unique.add(v); //TODO: pretty sure this is an acceptable change in syntax here: - //changes[ i ] = unique.length - 1; + //changes[i] = unique.length - 1; changes.add(unique.length - 1); } else { //print('Duplicate vertex found. $i could be using ${verticesMap[key]}'); //print('changes len ${changes.length} add at i = $i'); - //changes[ i ] = changes[ verticesMap[ key ] ]; + //changes[i] = changes[verticesMap[key]]; changes.add(changes[verticesMap[key]]); } @@ -397,26 +397,26 @@ class Geometry extends Object with WebGLGeometry { // check dups in (a, b, c, d) and convert to -> face3 - var o = [ face.a, face.b, face.c, face.d ]; + var o = [face.a, face.b, face.c, face.d]; - for ( var k = 3; k > 0; k -- ) { + for (var k = 3; k > 0; k --) { - if ( o.indexOf( face[ abcd[ k ] ] ) != k ) { + if (o.indexOf(face[abcd[k]]) != k) { // console.log('faces', face.a, face.b, face.c, face.d, 'dup at', k); - o.removeAt( k ); + o.removeAt(k); - this.faces[ i ] = new THREE.Face3( o[0], o[1], o[2], face.normal, face.color, face.materialIndex ); + this.faces[i] = new THREE.Face3(o[0], o[1], o[2], face.normal, face.color, face.materialIndex); - for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { + for (j = 0, jl = this.faceVertexUvs.length; j < jl; j ++) { - u = this.faceVertexUvs[ j ][ i ]; - if ( u ) u.removeAt( k ); + u = this.faceVertexUvs[j][i]; + if (u) u.removeAt(k); } - this.faces[ i ].vertexColors = face.vertexColors; + this.faces[i].vertexColors = face.vertexColors; break; } @@ -432,10 +432,42 @@ class Geometry extends Object with WebGLGeometry { return diff; } - clone() { + Geometry clone() { + var geometry = new Geometry(); - // TODO + var vertices = this.vertices; + for (var i = 0; i < vertices.length; i ++) { + geometry.vertices.add(vertices[i].clone()); + } + + var faces = this.faces; + + for (var i = 0; i < faces.length; i++) { + geometry.faces.add(faces[i].clone()); + } + + for (var i = 0; i < this.faceVertexUvs.length; i ++) { + var faceVertexUvs = this.faceVertexUvs[i]; + + if (geometry.faceVertexUvs[i] == null) { + geometry.faceVertexUvs[i] = []; + } + + for (var j = 0; j < faceVertexUvs.length; j ++) { + var uvs = faceVertexUvs[j], uvsCopy = []; + + for (var k = 0; k < uvs.length; k ++) { + var uv = uvs[k]; + + uvsCopy.add(uv.clone()); + } + + geometry.faceVertexUvs[i].add(uvsCopy); + } + } + + return geometry; } // Quick hack to allow setting new properties (used by the renderer) @@ -565,4 +597,4 @@ class BoundingSphere { num radius; Vector3 center; BoundingSphere({this.radius, this.center}); -} +} \ No newline at end of file diff --git a/lib/src/core/projector.dart b/lib/src/core/projector.dart index 3bd0aaaa..7d4654c1 100644 --- a/lib/src/core/projector.dart +++ b/lib/src/core/projector.dart @@ -15,12 +15,11 @@ part of three; class Projector { List _objectPool; List _vertexPool; - List _face4Pool; List _face3Pool; List _linePool; List _particlePool; - int _objectCount, _vertexCount, _face3Count, _face4Count, _lineCount, _particleCount; + int _objectCount, _vertexCount, _face3Count, _lineCount, _particleCount; RenderableObject _object; RenderableVertex _vertex; @@ -43,7 +42,6 @@ class Projector { : _objectPool = [], _vertexPool = [], _face3Pool = [], - _face4Pool = [], _linePool = [], _particlePool = [], @@ -223,7 +221,6 @@ class Projector { int side; _face3Count = 0; - _face4Count = 0; _lineCount = 0; _particleCount = 0; @@ -317,7 +314,7 @@ class Projector { if (side == DoubleSide || visible == (side == FrontSide)) { - _face = (face.size == 3) ? getNextFace3InPool() : getNextFace4InPool(); + _face = getNextFace3InPool(); _face.vertices = vtx.map((v) => v.clone()).toList(growable: false); @@ -355,7 +352,7 @@ class Projector { for (c = 0; c < cl; c++) { if (faceVertexUvs[c].length == 0) continue; - List uvs = faceVertexUvs[c][f]; + List uvs = faceVertexUvs[c][f]; if (uvs == null) continue; @@ -514,21 +511,6 @@ class Projector { return face; } - RenderableFace getNextFace4InPool() { - - RenderableFace4 face; - if (_face4Count < _face4Pool.length) { - face = (_face4Pool[_face4Count] != null) ? _face4Pool[_face4Count] : new RenderableFace4(); - } else { - face = new RenderableFace4(); - _face4Pool.add(face); - } - - _face4Count++; - - return face; - } - RenderableLine getNextLineInPool() { //TODO: make sure I've interpreted this logic correctly //RenderableLine line = _linePool[ _lineCount ] = _linePool[ _lineCount ] || new RenderableLine(); diff --git a/lib/src/core/uv.dart b/lib/src/core/uv.dart deleted file mode 100644 index 9dcfb0e4..00000000 --- a/lib/src/core/uv.dart +++ /dev/null @@ -1,39 +0,0 @@ -part of three; - -/** - * @author mr.doob / http://mrdoob.com/ - * - * Ported to Dart from JS by: - * @author rob silverton / http://www.unwrong.com/ - */ - -class UV { - double u, v; - - UV([this.u = 0.0, this.v = 0.0]); - - UV setValues(double u, double v) { - this.u = u; - this.v = v; - return this; - } - - UV copy(UV uv) { - u = uv.u; - v = uv.v; - - return this; - } - - lerpSelf(UV uv, num alpha) { - - u += (uv.u - u) * alpha; - v += (uv.v - v) * alpha; - - return this; - - } - - UV clone() => new UV(u, v); - -} diff --git a/lib/src/loaders/json_loader.dart b/lib/src/loaders/json_loader.dart index 1c65b76d..fdf3b66b 100644 --- a/lib/src/loaders/json_loader.dart +++ b/lib/src/loaders/json_loader.dart @@ -13,8 +13,7 @@ class JSONLoader extends Loader { JSONLoader({bool showStatus: false}) : super(showStatus); - load(url, LoadedCallback callback, {texturePath: null}) { - + void load(url, LoadedCallback callback, {texturePath: null}) { if (texturePath == null) { texturePath = Loader._extractUrlBase(url); } @@ -24,76 +23,51 @@ class JSONLoader extends Loader { _loadAjaxJSON(url, callback, texturePath); } - _loadAjaxJSON(String url, LoadedCallback callback, String texturePath, {LoadProgressCallback callbackProgress: - null}) { - - HttpRequest xhr = new HttpRequest(); + void _loadAjaxJSON(String url, LoadedCallback callback, String texturePath, {LoadProgressCallback callbackProgress}) { + var xhr = new HttpRequest(); var length = 0; xhr.onReadyStateChange.listen((Event e) { - if (xhr.readyState == HttpRequest.DONE) { - if (xhr.status == 200 || xhr.status == 0) { - if (!xhr.responseText.isEmpty) { - var json = JSON.decode(xhr.responseText); _createModel(json, callback, texturePath); - } else { - - print("THREE.JSONLoader: [$url] seems to be unreachable or file there is empty"); - + print("JSONLoader: [$url] seems to be unreachable or file there is empty"); } // in context of more complex asset initialization // do not block on single failed file // maybe should go even one more level up - onLoadComplete(); - } else { - - print("THREE.JSONLoader: Couldn't load [$url] [${xhr.status}]"); - + print("JSONLoader: Couldn't load [$url] [${xhr.status}]"); } - } else if (xhr.readyState == HttpRequest.LOADING) { - if (callbackProgress != null) { - if (length == 0) { - length = xhr.getResponseHeader("Content-Length"); - } callbackProgress({ "total": length, "loaded": xhr.responseText.length }); - } - } else if (xhr.readyState == HttpRequest.HEADERS_RECEIVED) { - length = xhr.getResponseHeader("Content-Length"); - } - }); xhr.open("GET", url); xhr.send(null); - } bool _isBitSet(value, position) => (value & (1 << position)) > 0; - _createModel(Map json, LoadedCallback callback, String texturePath) { - + void _createModel(Map json, LoadedCallback callback, String texturePath) { var geometry = new Geometry(), scale = (json.containsKey("scale")) ? 1.0 / json["scale"] : 1.0; @@ -112,42 +86,8 @@ class JSONLoader extends Loader { callback(geometry); } - _parseModel(Map json, Geometry geometry, num scale) { - - var i, - j, - fi, - - offset, - zLength, - nVertices, - - colorIndex, - normalIndex, - uvIndex, - materialIndex, - - type, - isQuad, - hasMaterial, - hasFaceUv, - hasFaceVertexUv, - hasFaceNormal, - hasFaceVertexNormal, - hasFaceColor, - hasFaceVertexColor, - - vertex, - face, - color, - normal, - - uvLayer, - uvs, - u, - v, - - faces = json["faces"], + void _parseModel(Map json, Geometry geometry, num scale) { + var faces = json["faces"], vertices = json["vertices"], normals = json["normals"], colors = json["colors"], @@ -156,282 +96,282 @@ class JSONLoader extends Loader { // disregard empty arrays - for (i = 0; i < json["uvs"].length; i++) { - + for (var i = 0; i < json["uvs"].length; i++) { if (!json["uvs"][i].isEmpty) nUvLayers++; - } geometry.faceUvs = new List(nUvLayers); geometry.faceVertexUvs = new List(nUvLayers); - for (i = 0; i < nUvLayers; i++) { - + for (var i = 0; i < nUvLayers; i++) { geometry.faceUvs[i] = new List(faces.length); geometry.faceVertexUvs[i] = new List(faces.length); - } - offset = 0; - zLength = vertices.length; + var offset = 0; + var zLength = vertices.length; while (offset < zLength) { - - vertex = new Vector3.zero(); + var vertex = new Vector3.zero(); vertex.x = vertices[offset++] * scale; vertex.y = vertices[offset++] * scale; vertex.z = vertices[offset++] * scale; geometry.vertices.add(vertex); - } offset = 0; zLength = faces.length; while (offset < zLength) { - - type = faces[offset++]; - - - isQuad = _isBitSet(type, 0); - hasMaterial = _isBitSet(type, 1); - hasFaceUv = _isBitSet(type, 2); - hasFaceVertexUv = _isBitSet(type, 3); - hasFaceNormal = _isBitSet(type, 4); - hasFaceVertexNormal = _isBitSet(type, 5); - hasFaceColor = _isBitSet(type, 6); - hasFaceVertexColor = _isBitSet(type, 7); - + var type = faces[offset++]; + + var isQuad = _isBitSet(type, 0); + var hasMaterial = _isBitSet(type, 1); + var hasFaceUv = _isBitSet(type, 2); + var hasFaceVertexUv = _isBitSet(type, 3); + var hasFaceNormal = _isBitSet(type, 4); + var hasFaceVertexNormal = _isBitSet(type, 5); + var hasFaceColor = _isBitSet(type, 6); + var hasFaceVertexColor = _isBitSet(type, 7); + if (isQuad) { + var faceA = new Face3(); + faceA.a = faces[offset]; + faceA.b = faces[offset + 1]; + faceA.c = faces[offset + 3]; + + var faceB = new Face3(); + faceB.a = faces[offset + 1]; + faceB.b = faces[offset + 2]; + faceB.c = faces[offset + 3]; + + offset += 4; + + if (hasMaterial) { + var materialIndex = faces[offset ++]; + faceA.materialIndex = materialIndex; + faceB.materialIndex = materialIndex; + } - face = new Face4(); - - face.a = faces[offset++]; - face.b = faces[offset++]; - face.c = faces[offset++]; - face.d = faces[offset++]; - - nVertices = 4; - - } else { - - face = new Face3(); + // to get face <=> uv index correspondence - face.a = faces[offset++]; - face.b = faces[offset++]; - face.c = faces[offset++]; + var fi = geometry.faces.length; - nVertices = 3; + if (hasFaceVertexUv) { + for (var i = 0; i < nUvLayers; i ++) { + var uvLayer = json['uvs'][i]; - } + geometry.faceVertexUvs[i][fi] = []; + geometry.faceVertexUvs[i][fi + 1] = []; - if (hasMaterial) { + for (var j = 0; j < 4; j ++) { - materialIndex = faces[offset++]; - face.materialIndex = materialIndex; + var uvIndex = faces[offset ++]; - } + var u = uvLayer[uvIndex * 2]; + var v = uvLayer[uvIndex * 2 + 1]; - // to get face <=> uv index correspondence + var uv = new Vector2(u, v); - fi = geometry.faces.length; + if (j != 2) geometry.faceVertexUvs[i][fi].add(uv); + if (j != 0) geometry.faceVertexUvs[i][fi + 1].add(uv); + } + } + } - if (hasFaceUv) { + if (hasFaceNormal) { + var normalIndex = faces[offset ++] * 3; - for (i = 0; i < nUvLayers; i++) { + faceA.normal.setValues( + normals[normalIndex++].toDouble(), + normals[normalIndex++].toDouble(), + normals[normalIndex].toDouble() + ); - uvLayer = json["uvs"][i]; + faceB.normal.setFrom(faceA.normal); + } - uvIndex = faces[offset++]; + if (hasFaceVertexNormal) { + for (var i = 0; i < 4; i ++) { + var normalIndex = faces[offset ++] * 3; - u = uvLayer[uvIndex * 2]; - v = uvLayer[uvIndex * 2 + 1]; + var normal = new Vector3( + normals[normalIndex++].toDouble(), + normals[normalIndex++].toDouble(), + normals[normalIndex].toDouble() + ); - geometry.faceUvs[i][fi] = new UV(u.toDouble(), v.toDouble()); + if (i != 2) faceA.vertexNormals.add(normal); + if (i != 0) faceB.vertexNormals.add(normal); + } } - } - - if (hasFaceVertexUv) { - - for (i = 0; i < nUvLayers; i++) { - uvLayer = json["uvs"][i]; + if (hasFaceColor) { + var colorIndex = faces[offset ++]; + var hex = colors[colorIndex]; - uvs = new List(nVertices); - - for (j = 0; j < nVertices; j++) { + faceA.color.setHex(hex); + faceB.color.setHex(hex); + } - uvIndex = faces[offset++]; - u = uvLayer[uvIndex * 2]; - v = uvLayer[uvIndex * 2 + 1]; + if (hasFaceVertexColor) { + for (var i = 0; i < 4; i ++) { + var colorIndex = faces[offset ++]; + var hex = colors[colorIndex]; - uvs[j] = new UV(u.toDouble(), v.toDouble()); + if (i != 2) faceA.vertexColors.add(new Color(hex)); + if (i != 0) faceB.vertexColors.add(new Color(hex)); } - - geometry.faceVertexUvs[i][fi] = uvs; - } - } - - if (hasFaceNormal) { - - normalIndex = faces[offset++] * 3; + geometry.faces.add(faceA); + geometry.faces.add(faceB); - normal = new Vector3.zero(); - - normal.x = normals[normalIndex++].toDouble(); - normal.y = normals[normalIndex++].toDouble(); - normal.z = normals[normalIndex].toDouble(); - - face.normal = normal; + } else { + var face = new Face3(); + face.a = faces[offset ++]; + face.b = faces[offset ++]; + face.c = faces[offset ++]; + + if (hasMaterial) { + var materialIndex = faces[offset ++]; + face.materialIndex = materialIndex; + } - } + // to get face <=> uv index correspondence - if (hasFaceVertexNormal) { + var fi = geometry.faces.length; - for (i = 0; i < nVertices; i++) { + if (hasFaceVertexUv) { + for (var i = 0; i < nUvLayers; i ++) { + var uvLayer = json['uvs'][i]; - normalIndex = faces[offset++] * 3; + geometry.faceVertexUvs[i][fi] = []; - normal = new Vector3.zero(); + for (var j = 0; j < 3; j ++) { + var uvIndex = faces[offset ++]; - normal.x = normals[normalIndex++].toDouble(); - normal.y = normals[normalIndex++].toDouble(); - normal.z = normals[normalIndex].toDouble(); + var u = uvLayer[uvIndex * 2]; + var v = uvLayer[uvIndex * 2 + 1]; - face.vertexNormals.add(normal); + var uv = new Vector2(u, v); + geometry.faceVertexUvs[i][fi].add(uv); + } + } } - } - - - if (hasFaceColor) { - - colorIndex = faces[offset++]; + if (hasFaceNormal) { + var normalIndex = faces[offset ++] * 3; - color = new Color(colors[colorIndex]); - face.color = color; - - } + face.normal.setValues( + normals[normalIndex ++], + normals[normalIndex ++], + normals[normalIndex] + ); + } + if (hasFaceVertexNormal) { + for (var i = 0; i < 3; i ++) { + var normalIndex = faces[offset ++] * 3; - if (hasFaceVertexColor) { + var normal = new Vector3( + normals[normalIndex ++], + normals[normalIndex ++], + normals[normalIndex] + ); - for (i = 0; i < nVertices; i++) { + face.vertexNormals.add(normal); + } + } - colorIndex = faces[offset++]; - color = new Color(colors[colorIndex]); - face.vertexColors.add(color); + if (hasFaceColor) { + var colorIndex = faces[offset ++]; + face.color.setHex(colors[colorIndex]); + } + if (hasFaceVertexColor) { + for (var i = 0; i < 3; i ++) { + var colorIndex = faces[offset ++]; + face.vertexColors.add(new Color(colors[colorIndex])); + } } + geometry.faces.add(face); } - - geometry.faces.add(face); - } - } - _parseSkin(Map json, Geometry geometry) { - - var i, l, x, y, z, w, a, b, c, d; - + void _parseSkin(Map json, Geometry geometry) { if (json.containsKey("skinWeights")) { - - l = json["skinWeights"].length; - for (i = 0; i < l; i += 2) { - - x = json["skinWeights"][i]; - y = json["skinWeights"][i + 1]; - z = 0.0; - w = 0.0; + var l = json["skinWeights"].length; + for (var i = 0; i < l; i += 2) { + var x = json["skinWeights"][i]; + var y = json["skinWeights"][i + 1]; + var z = 0.0; + var w = 0.0; geometry.skinWeights.add(new Vector4(x.toDouble(), y.toDouble(), z.toDouble(), w.toDouble())); - } - } if (json.containsKey("skinIndices")) { - - l = json["skinIndices"].length; - for (i = 0; i < l; i += 2) { - - a = json["skinIndices"][i]; - b = json["skinIndices"][i + 1]; - c = 0.0; - d = 0.0; + var l = json["skinIndices"].length; + for (var i = 0; i < l; i += 2) { + var a = json["skinIndices"][i]; + var b = json["skinIndices"][i + 1]; + var c = 0.0; + var d = 0.0; geometry.skinIndices.add(new Vector4(a.toDouble(), b.toDouble(), c.toDouble(), d.toDouble())); - } - } geometry.bones = json["bones"]; geometry.animation = json["animation"]; - } - _parseMorphing(Map json, Geometry geometry, num scale) { - + void _parseMorphing(Map json, Geometry geometry, num scale) { if (json.containsKey("morphTargets")) { - - var i, l, v, vl, dstVertices, srcVertices; - geometry.morphTargets = new List(json["morphTargets"].length); - for (i = 0; i < geometry.morphTargets.length; i++) { - + for (var i = 0; i < geometry.morphTargets.length; i++) { geometry.morphTargets[i] = new MorphTarget(name: json["morphTargets"][i]["name"], vertices: []); - dstVertices = geometry.morphTargets[i].vertices; - srcVertices = json["morphTargets"][i]["vertices"]; - - vl = srcVertices.length; - for (v = 0; v < vl; v += 3) { + var dstVertices = geometry.morphTargets[i].vertices; + var srcVertices = json["morphTargets"][i]["vertices"]; + var vl = srcVertices.length; + for (var v = 0; v < vl; v += 3) { var vertex = new Vector3.zero(); vertex.x = srcVertices[v] * scale; vertex.y = srcVertices[v + 1] * scale; vertex.z = srcVertices[v + 2] * scale; dstVertices.add(vertex); - } - } - } if (json.containsKey("morphColors")) { - - var i, l, c, cl, dstColors, srcColors, color; - geometry.morphColors = new List(json["morphColors"].length); - for (i = 0; i < geometry.morphColors.length; i++) { + for (var i = 0; i < geometry.morphColors.length; i++) { + var dstColors = []; + var srcColors = json["morphColors"][i]["colors"]; - dstColors = []; - srcColors = json["morphColors"][i]["colors"]; - - cl = srcColors.length; - for (c = 0; c < cl; c += 3) { - - color = new Color(0xffaa00); + var cl = srcColors.length; + for (var c = 0; c < cl; c += 3) { + var color = new Color(0xffaa00); color.setRGB(srcColors[c], srcColors[c + 1], srcColors[c + 2]); dstColors.add(color); - } geometry.morphColors[i] = new MorphColors(name: json["morphColors"][i]["name"], colors: dstColors); diff --git a/lib/src/loaders/obj_loader.dart b/lib/src/loaders/obj_loader.dart index e20c1301..4737db5d 100644 --- a/lib/src/loaders/obj_loader.dart +++ b/lib/src/loaders/obj_loader.dart @@ -159,7 +159,7 @@ class OBJLoader extends Loader { } else if ((result = uv_pattern.firstMatch(line)) != null) { // ["vt 0.1 0.2", "0.1", "0.2"] - uvs.add(new UV(double.parse(result[1]), double.parse(result[2]))); + uvs.add(new Vector2(double.parse(result[1]), double.parse(result[2]))); } else if ((result = face_pattern1.firstMatch(line)) != null) { diff --git a/lib/src/renderers/renderables/renderable_face4.dart b/lib/src/renderers/renderables/renderable_face4.dart deleted file mode 100644 index 644f5687..00000000 --- a/lib/src/renderers/renderables/renderable_face4.dart +++ /dev/null @@ -1,19 +0,0 @@ -part of three; - -/** - * @author mr.doob / http://mrdoob.com/ - * - * Ported to Dart from JS by: - * @author rob silverton / http://www.unwrong.com/ - */ - -class RenderableFace4 extends RenderableFace { - - RenderableFace4() : super(4); - - RenderableVertex get v1 => vertices[0]; - RenderableVertex get v2 => vertices[1]; - RenderableVertex get v3 => vertices[2]; - RenderableVertex get v4 => vertices[3]; - -} diff --git a/lib/src/renderers/web_gl_renderer.dart b/lib/src/renderers/web_gl_renderer.dart index a3fc3ab4..ccae6113 100644 --- a/lib/src/renderers/web_gl_renderer.dart +++ b/lib/src/renderers/web_gl_renderer.dart @@ -913,11 +913,10 @@ class WebGLRenderer implements Renderer { var geometry = object.geometry, faces3 = geometryGroup.faces3, - faces4 = geometryGroup.faces4, - nvertices = faces3.length * 3 + faces4.length * 4, - ntris = faces3.length * 1 + faces4.length * 2, - nlines = faces3.length * 3 + faces4.length * 4; + nvertices = faces3.length * 3, + ntris = faces3.length * 1, + nlines = faces3.length * 3; Material material = getBufferMaterial(object, geometryGroup); @@ -1952,7 +1951,6 @@ class WebGLRenderer implements Renderer { vertices = geometry.vertices, chunk_faces3 = geometryGroup.faces3, - chunk_faces4 = geometryGroup.faces4, obj_faces = geometry.faces, obj_uvs = (geometry.faceVertexUvs.length == 0) ? [] : geometry.faceVertexUvs[0], @@ -1994,36 +1992,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - v1 = vertices[face.a]; - v2 = vertices[face.b]; - v3 = vertices[face.c]; - v4 = vertices[face.d]; - - vertexArray[offset] = v1.x; - vertexArray[offset + 1] = v1.y; - vertexArray[offset + 2] = v1.z; - - vertexArray[offset + 3] = v2.x; - vertexArray[offset + 4] = v2.y; - vertexArray[offset + 5] = v2.z; - - vertexArray[offset + 6] = v3.x; - vertexArray[offset + 7] = v3.y; - vertexArray[offset + 8] = v3.z; - - vertexArray[offset + 9] = v4.x; - vertexArray[offset + 10] = v4.y; - vertexArray[offset + 11] = v4.z; - - offset += 12; - - } - _gl.bindBuffer(gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer); _gl.bufferDataTyped(gl.ARRAY_BUFFER, vertexArray, hint); @@ -2104,85 +2072,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - chf = chunk_faces4[f]; - face = obj_faces[chf]; - - // morph positions - - v1 = morphTargets[vk].vertices[face.a]; - v2 = morphTargets[vk].vertices[face.b]; - v3 = morphTargets[vk].vertices[face.c]; - v4 = morphTargets[vk].vertices[face.d]; - - vka = morphTargetsArrays[vk]; - - vka[offset_morphTarget] = v1.x; - vka[offset_morphTarget + 1] = v1.y; - vka[offset_morphTarget + 2] = v1.z; - - vka[offset_morphTarget + 3] = v2.x; - vka[offset_morphTarget + 4] = v2.y; - vka[offset_morphTarget + 5] = v2.z; - - vka[offset_morphTarget + 6] = v3.x; - vka[offset_morphTarget + 7] = v3.y; - vka[offset_morphTarget + 8] = v3.z; - - vka[offset_morphTarget + 9] = v4.x; - vka[offset_morphTarget + 10] = v4.y; - vka[offset_morphTarget + 11] = v4.z; - - // morph normals - - if ((material is Morphing) && (material as Morphing).morphNormals) { - - if (needsSmoothNormals) { - - faceVertexNormals = morphNormals[vk].vertexNormals[chf]; - - n1 = faceVertexNormals.a; - n2 = faceVertexNormals.b; - n3 = faceVertexNormals.c; - n4 = faceVertexNormals.d; - - } else { - - n1 = morphNormals[vk].faceNormals[chf]; - n2 = n1; - n3 = n1; - n4 = n1; - - } - - nka = morphNormalsArrays[vk]; - - nka[offset_morphTarget] = n1.x; - nka[offset_morphTarget + 1] = n1.y; - nka[offset_morphTarget + 2] = n1.z; - - nka[offset_morphTarget + 3] = n2.x; - nka[offset_morphTarget + 4] = n2.y; - nka[offset_morphTarget + 5] = n2.z; - - nka[offset_morphTarget + 6] = n3.x; - nka[offset_morphTarget + 7] = n3.y; - nka[offset_morphTarget + 8] = n3.z; - - nka[offset_morphTarget + 9] = n4.x; - nka[offset_morphTarget + 10] = n4.y; - nka[offset_morphTarget + 11] = n4.z; - - } - - // - - offset_morphTarget += 12; - - } - _gl.bindBuffer(gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[vk]); _gl.bufferDataTyped(gl.ARRAY_BUFFER, morphTargetsArrays[vk], hint); @@ -2250,69 +2139,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - // weights - - sw1 = obj_skinWeights[face.a]; - sw2 = obj_skinWeights[face.b]; - sw3 = obj_skinWeights[face.c]; - sw4 = obj_skinWeights[face.d]; - - skinWeightArray[offset_skin] = sw1.x; - skinWeightArray[offset_skin + 1] = sw1.y; - skinWeightArray[offset_skin + 2] = sw1.z; - skinWeightArray[offset_skin + 3] = sw1.w; - - skinWeightArray[offset_skin + 4] = sw2.x; - skinWeightArray[offset_skin + 5] = sw2.y; - skinWeightArray[offset_skin + 6] = sw2.z; - skinWeightArray[offset_skin + 7] = sw2.w; - - skinWeightArray[offset_skin + 8] = sw3.x; - skinWeightArray[offset_skin + 9] = sw3.y; - skinWeightArray[offset_skin + 10] = sw3.z; - skinWeightArray[offset_skin + 11] = sw3.w; - - skinWeightArray[offset_skin + 12] = sw4.x; - skinWeightArray[offset_skin + 13] = sw4.y; - skinWeightArray[offset_skin + 14] = sw4.z; - skinWeightArray[offset_skin + 15] = sw4.w; - - // indices - - si1 = obj_skinIndices[face.a]; - si2 = obj_skinIndices[face.b]; - si3 = obj_skinIndices[face.c]; - si4 = obj_skinIndices[face.d]; - - skinIndexArray[offset_skin] = si1.x; - skinIndexArray[offset_skin + 1] = si1.y; - skinIndexArray[offset_skin + 2] = si1.z; - skinIndexArray[offset_skin + 3] = si1.w; - - skinIndexArray[offset_skin + 4] = si2.x; - skinIndexArray[offset_skin + 5] = si2.y; - skinIndexArray[offset_skin + 6] = si2.z; - skinIndexArray[offset_skin + 7] = si2.w; - - skinIndexArray[offset_skin + 8] = si3.x; - skinIndexArray[offset_skin + 9] = si3.y; - skinIndexArray[offset_skin + 10] = si3.z; - skinIndexArray[offset_skin + 11] = si3.w; - - skinIndexArray[offset_skin + 12] = si4.x; - skinIndexArray[offset_skin + 13] = si4.y; - skinIndexArray[offset_skin + 14] = si4.z; - skinIndexArray[offset_skin + 15] = si4.w; - - offset_skin += 16; - - } - if (offset_skin > 0) { _gl.bindBuffer(gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer); @@ -2365,50 +2191,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - vertexColors = face.vertexColors; - faceColor = face.color; - - if (vertexColors.length == 4 && (material.vertexColors == VertexColors)) { - - c1 = vertexColors[0]; - c2 = vertexColors[1]; - c3 = vertexColors[2]; - c4 = vertexColors[3]; - - } else { - - c1 = faceColor; - c2 = faceColor; - c3 = faceColor; - c4 = faceColor; - - } - - colorArray[offset_color] = c1.r; - colorArray[offset_color + 1] = c1.g; - colorArray[offset_color + 2] = c1.b; - - colorArray[offset_color + 3] = c2.r; - colorArray[offset_color + 4] = c2.g; - colorArray[offset_color + 5] = c2.b; - - colorArray[offset_color + 6] = c3.r; - colorArray[offset_color + 7] = c3.g; - colorArray[offset_color + 8] = c3.b; - - colorArray[offset_color + 9] = c4.r; - colorArray[offset_color + 10] = c4.g; - colorArray[offset_color + 11] = c4.b; - - offset_color += 12; - - } - if (offset_color > 0) { _gl.bindBuffer(gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer); @@ -2450,42 +2232,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - vertexTangents = face.vertexTangents; - - t1 = vertexTangents[0]; - t2 = vertexTangents[1]; - t3 = vertexTangents[2]; - t4 = vertexTangents[3]; - - tangentArray[offset_tangent] = t1.x; - tangentArray[offset_tangent + 1] = t1.y; - tangentArray[offset_tangent + 2] = t1.z; - tangentArray[offset_tangent + 3] = t1.w; - - tangentArray[offset_tangent + 4] = t2.x; - tangentArray[offset_tangent + 5] = t2.y; - tangentArray[offset_tangent + 6] = t2.z; - tangentArray[offset_tangent + 7] = t2.w; - - tangentArray[offset_tangent + 8] = t3.x; - tangentArray[offset_tangent + 9] = t3.y; - tangentArray[offset_tangent + 10] = t3.z; - tangentArray[offset_tangent + 11] = t3.w; - - tangentArray[offset_tangent + 12] = t4.x; - tangentArray[offset_tangent + 13] = t4.y; - tangentArray[offset_tangent + 14] = t4.z; - tangentArray[offset_tangent + 15] = t4.w; - - offset_tangent += 16; - - } - _gl.bindBuffer(gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer); _gl.bufferDataTyped(gl.ARRAY_BUFFER, tangentArray, hint); @@ -2531,44 +2277,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - vertexNormals = face.vertexNormals; - faceNormal = face.normal; - - if (vertexNormals.length == 4 && needsSmoothNormals) { - - for (i = 0; i < 4; i++) { - - vn = vertexNormals[i]; - - normalArray[offset_normal] = vn.x; - normalArray[offset_normal + 1] = vn.y; - normalArray[offset_normal + 2] = vn.z; - - offset_normal += 3; - - } - - } else { - - for (i = 0; i < 4; i++) { - - normalArray[offset_normal] = faceNormal.x; - normalArray[offset_normal + 1] = faceNormal.y; - normalArray[offset_normal + 2] = faceNormal.z; - - offset_normal += 3; - - } - - } - - } - _gl.bindBuffer(gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer); _gl.bufferDataTyped(gl.ARRAY_BUFFER, normalArray, hint); @@ -2589,30 +2297,8 @@ class WebGLRenderer implements Renderer { uvi = uv[i]; - uvArray[offset_uv] = uvi.u; - uvArray[offset_uv + 1] = uvi.v; - - offset_uv += 2; - - } - - } - - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - fi = chunk_faces4[f]; - - uv = obj_uvs[fi]; - - if (uv == null) continue; - - for (i = 0; i < 4; i++) { - - uvi = uv[i]; - - uvArray[offset_uv] = uvi.u; - uvArray[offset_uv + 1] = uvi.v; + uvArray[offset_uv] = uvi.x; + uvArray[offset_uv + 1] = uvi.y; offset_uv += 2; @@ -2653,28 +2339,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - fi = chunk_faces4[f]; - - uv2 = obj_uvs2[fi]; - - if (uv2 == null) continue; - - for (i = 0; i < 4; i++) { - - uv2i = uv2[i]; - - uv2Array[offset_uv2] = uv2i.u; - uv2Array[offset_uv2 + 1] = uv2i.v; - - offset_uv2 += 2; - - } - - } - if (offset_uv2 > 0) { _gl.bindBuffer(gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer); @@ -2710,37 +2374,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - faceArray[offset_face] = vertexIndex; - faceArray[offset_face + 1] = vertexIndex + 1; - faceArray[offset_face + 2] = vertexIndex + 3; - - faceArray[offset_face + 3] = vertexIndex + 1; - faceArray[offset_face + 4] = vertexIndex + 2; - faceArray[offset_face + 5] = vertexIndex + 3; - - offset_face += 6; - - lineArray[offset_line] = vertexIndex; - lineArray[offset_line + 1] = vertexIndex + 1; - - lineArray[offset_line + 2] = vertexIndex; - lineArray[offset_line + 3] = vertexIndex + 3; - - lineArray[offset_line + 4] = vertexIndex + 1; - lineArray[offset_line + 5] = vertexIndex + 2; - - lineArray[offset_line + 6] = vertexIndex + 2; - lineArray[offset_line + 7] = vertexIndex + 3; - - offset_line += 8; - - vertexIndex += 4; - - } - _gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer); _gl.bufferDataTyped(gl.ELEMENT_ARRAY_BUFFER, faceArray, hint); @@ -2778,20 +2411,7 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - customAttribute.array[offset_custom] = customAttribute.value[face.a]; - customAttribute.array[offset_custom + 1] = customAttribute.value[face.b]; - customAttribute.array[offset_custom + 2] = customAttribute.value[face.c]; - customAttribute.array[offset_custom + 3] = customAttribute.value[face.d]; - - offset_custom += 4; - - } - + } else if (customAttribute.boundTo == "faces") { fl = chunk_faces3.length; @@ -2807,20 +2427,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - value = customAttribute.value[chunk_faces4[f]]; - - customAttribute.array[offset_custom] = value; - customAttribute.array[offset_custom + 1] = value; - customAttribute.array[offset_custom + 2] = value; - customAttribute.array[offset_custom + 3] = value; - - offset_custom += 4; - - } - } } else if (customAttribute.size == 2) { @@ -2849,32 +2455,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - v1 = customAttribute.value[face.a]; - v2 = customAttribute.value[face.b]; - v3 = customAttribute.value[face.c]; - v4 = customAttribute.value[face.d]; - - customAttribute.array[offset_custom] = v1.x; - customAttribute.array[offset_custom + 1] = v1.y; - - customAttribute.array[offset_custom + 2] = v2.x; - customAttribute.array[offset_custom + 3] = v2.y; - - customAttribute.array[offset_custom + 4] = v3.x; - customAttribute.array[offset_custom + 5] = v3.y; - - customAttribute.array[offset_custom + 6] = v4.x; - customAttribute.array[offset_custom + 7] = v4.y; - - offset_custom += 8; - - } - } else if (customAttribute.boundTo == "faces") { fl = chunk_faces3.length; @@ -2899,32 +2479,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - value = customAttribute.value[chunk_faces4[f]]; - - v1 = value; - v2 = value; - v3 = value; - v4 = value; - - customAttribute.array[offset_custom] = v1.x; - customAttribute.array[offset_custom + 1] = v1.y; - - customAttribute.array[offset_custom + 2] = v2.x; - customAttribute.array[offset_custom + 3] = v2.y; - - customAttribute.array[offset_custom + 4] = v3.x; - customAttribute.array[offset_custom + 5] = v3.y; - - customAttribute.array[offset_custom + 6] = v4.x; - customAttribute.array[offset_custom + 7] = v4.y; - - offset_custom += 8; - - } - } } else if (customAttribute.size == 3) { @@ -2968,36 +2522,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - v1 = customAttribute.value[face.a]; - v2 = customAttribute.value[face.b]; - v3 = customAttribute.value[face.c]; - v4 = customAttribute.value[face.d]; - - customAttribute.array[offset_custom] = v1[pp[0]]; - customAttribute.array[offset_custom + 1] = v1[pp[1]]; - customAttribute.array[offset_custom + 2] = v1[pp[2]]; - - customAttribute.array[offset_custom + 3] = v2[pp[0]]; - customAttribute.array[offset_custom + 4] = v2[pp[1]]; - customAttribute.array[offset_custom + 5] = v2[pp[2]]; - - customAttribute.array[offset_custom + 6] = v3[pp[0]]; - customAttribute.array[offset_custom + 7] = v3[pp[1]]; - customAttribute.array[offset_custom + 8] = v3[pp[2]]; - - customAttribute.array[offset_custom + 9] = v4[pp[0]]; - customAttribute.array[offset_custom + 10] = v4[pp[1]]; - customAttribute.array[offset_custom + 11] = v4[pp[2]]; - - offset_custom += 12; - - } - } else if (customAttribute.boundTo == "faces") { fl = chunk_faces3.length; @@ -3025,36 +2549,7 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - value = customAttribute.value[chunk_faces4[f]]; - - v1 = value; - v2 = value; - v3 = value; - v4 = value; - - customAttribute.array[offset_custom] = v1[pp[0]]; - customAttribute.array[offset_custom + 1] = v1[pp[1]]; - customAttribute.array[offset_custom + 2] = v1[pp[2]]; - - customAttribute.array[offset_custom + 3] = v2[pp[0]]; - customAttribute.array[offset_custom + 4] = v2[pp[1]]; - customAttribute.array[offset_custom + 5] = v2[pp[2]]; - - customAttribute.array[offset_custom + 6] = v3[pp[0]]; - customAttribute.array[offset_custom + 7] = v3[pp[1]]; - customAttribute.array[offset_custom + 8] = v3[pp[2]]; - - customAttribute.array[offset_custom + 9] = v4[pp[0]]; - customAttribute.array[offset_custom + 10] = v4[pp[1]]; - customAttribute.array[offset_custom + 11] = v4[pp[2]]; - - offset_custom += 12; - - } - + } else if (customAttribute.boundTo == "faceVertices") { fl = chunk_faces3.length; @@ -3082,36 +2577,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - value = customAttribute.value[chunk_faces4[f]]; - - v1 = value[0]; - v2 = value[1]; - v3 = value[2]; - v4 = value[3]; - - customAttribute.array[offset_custom] = v1[pp[0]]; - customAttribute.array[offset_custom + 1] = v1[pp[1]]; - customAttribute.array[offset_custom + 2] = v1[pp[2]]; - - customAttribute.array[offset_custom + 3] = v2[pp[0]]; - customAttribute.array[offset_custom + 4] = v2[pp[1]]; - customAttribute.array[offset_custom + 5] = v2[pp[2]]; - - customAttribute.array[offset_custom + 6] = v3[pp[0]]; - customAttribute.array[offset_custom + 7] = v3[pp[1]]; - customAttribute.array[offset_custom + 8] = v3[pp[2]]; - - customAttribute.array[offset_custom + 9] = v4[pp[0]]; - customAttribute.array[offset_custom + 10] = v4[pp[1]]; - customAttribute.array[offset_custom + 11] = v4[pp[2]]; - - offset_custom += 12; - - } - } } else if (customAttribute.size == 4) { @@ -3145,41 +2610,6 @@ class WebGLRenderer implements Renderer { offset_custom += 12; } - - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - face = obj_faces[chunk_faces4[f]]; - - v1 = customAttribute.value[face.a]; - v2 = customAttribute.value[face.b]; - v3 = customAttribute.value[face.c]; - v4 = customAttribute.value[face.d]; - - customAttribute.array[offset_custom] = v1.x; - customAttribute.array[offset_custom + 1] = v1.y; - customAttribute.array[offset_custom + 2] = v1.z; - customAttribute.array[offset_custom + 3] = v1.w; - - customAttribute.array[offset_custom + 4] = v2.x; - customAttribute.array[offset_custom + 5] = v2.y; - customAttribute.array[offset_custom + 6] = v2.z; - customAttribute.array[offset_custom + 7] = v2.w; - - customAttribute.array[offset_custom + 8] = v3.x; - customAttribute.array[offset_custom + 9] = v3.y; - customAttribute.array[offset_custom + 10] = v3.z; - customAttribute.array[offset_custom + 11] = v3.w; - - customAttribute.array[offset_custom + 12] = v4.x; - customAttribute.array[offset_custom + 13] = v4.y; - customAttribute.array[offset_custom + 14] = v4.z; - customAttribute.array[offset_custom + 15] = v4.w; - - offset_custom += 16; - - } - } else if (customAttribute.boundTo == "faces") { fl = chunk_faces3.length; @@ -3210,40 +2640,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - value = customAttribute.value[chunk_faces4[f]]; - - v1 = value; - v2 = value; - v3 = value; - v4 = value; - - customAttribute.array[offset_custom] = v1.x; - customAttribute.array[offset_custom + 1] = v1.y; - customAttribute.array[offset_custom + 2] = v1.z; - customAttribute.array[offset_custom + 3] = v1.w; - - customAttribute.array[offset_custom + 4] = v2.x; - customAttribute.array[offset_custom + 5] = v2.y; - customAttribute.array[offset_custom + 6] = v2.z; - customAttribute.array[offset_custom + 7] = v2.w; - - customAttribute.array[offset_custom + 8] = v3.x; - customAttribute.array[offset_custom + 9] = v3.y; - customAttribute.array[offset_custom + 10] = v3.z; - customAttribute.array[offset_custom + 11] = v3.w; - - customAttribute.array[offset_custom + 12] = v4.x; - customAttribute.array[offset_custom + 13] = v4.y; - customAttribute.array[offset_custom + 14] = v4.z; - customAttribute.array[offset_custom + 15] = v4.w; - - offset_custom += 16; - - } - } else if (customAttribute.boundTo == "faceVertices") { fl = chunk_faces3.length; @@ -3274,40 +2670,6 @@ class WebGLRenderer implements Renderer { } - fl = chunk_faces4.length; - for (f = 0; f < fl; f++) { - - value = customAttribute.value[chunk_faces4[f]]; - - v1 = value[0]; - v2 = value[1]; - v3 = value[2]; - v4 = value[3]; - - customAttribute.array[offset_custom] = v1.x; - customAttribute.array[offset_custom + 1] = v1.y; - customAttribute.array[offset_custom + 2] = v1.z; - customAttribute.array[offset_custom + 3] = v1.w; - - customAttribute.array[offset_custom + 4] = v2.x; - customAttribute.array[offset_custom + 5] = v2.y; - customAttribute.array[offset_custom + 6] = v2.z; - customAttribute.array[offset_custom + 7] = v2.w; - - customAttribute.array[offset_custom + 8] = v3.x; - customAttribute.array[offset_custom + 9] = v3.y; - customAttribute.array[offset_custom + 10] = v3.z; - customAttribute.array[offset_custom + 11] = v3.w; - - customAttribute.array[offset_custom + 12] = v4.x; - customAttribute.array[offset_custom + 13] = v4.y; - customAttribute.array[offset_custom + 14] = v4.z; - customAttribute.array[offset_custom + 15] = v4.w; - - offset_custom += 16; - - } - } } @@ -4640,7 +4002,6 @@ class WebGLRenderer implements Renderer { geometry.geometryGroups[groupHash] = new WebGLGeometry() ..faces3 = [] - ..faces4 = [] ..materialIndex = int.parse(materialIndex) ..verticesCount = 0 ..numMorphTargets = numMorphTargets @@ -4658,7 +4019,6 @@ class WebGLRenderer implements Renderer { geometry.geometryGroups[groupHash] = new WebGLGeometry() ..faces3 = [] - ..faces4 = [] ..materialIndex = int.parse(materialIndex) ..verticesCount = 0 ..numMorphTargets = numMorphTargets @@ -4668,15 +4028,8 @@ class WebGLRenderer implements Renderer { } - if (face.size == 3) { + geometry.geometryGroups[groupHash].faces3.add(f); - geometry.geometryGroups[groupHash].faces3.add(f); - - } else { - - geometry.geometryGroups[groupHash].faces4.add(f); - - } geometry.geometryGroups[groupHash].verticesCount += vertices; @@ -7679,7 +7032,7 @@ class WebGLGeometry { int verticesCount; - List faces3, faces4; + List faces3; int numMorphTargets, numMorphNormals; int materialIndex = 0; diff --git a/lib/three.dart b/lib/three.dart index 16711c10..1180eb78 100644 --- a/lib/three.dart +++ b/lib/three.dart @@ -31,14 +31,12 @@ part 'src/core/object3d.dart'; part 'src/core/color.dart'; part 'src/core/face.dart'; part 'src/core/face3.dart'; -part 'src/core/face4.dart'; part 'src/core/frustum.dart'; part 'src/core/morph_colors.dart'; part 'src/core/morph_target.dart'; part 'src/core/geometry.dart'; part 'src/core/projector.dart'; part 'src/core/ray.dart'; -part 'src/core/uv.dart'; part 'src/core/rectangle.dart'; part 'src/core/buffer_geometry.dart'; part 'src/core/event_emitter.dart'; @@ -68,6 +66,7 @@ part 'extras/geometries/text_geometry.dart'; part 'extras/geometries/torus_geometry.dart'; part 'extras/geometries/torus_knot_geometry.dart'; part 'extras/geometries/tube_geometry.dart'; +part 'extras/geometries/ring_geometry.dart'; part 'extras/core/curve.dart'; part 'extras/core/curve_path.dart'; @@ -132,7 +131,6 @@ part 'src/renderers/renderables/renderable_object.dart'; part 'src/renderers/renderables/renderable_vertex.dart'; part 'src/renderers/renderables/renderable_face.dart'; part 'src/renderers/renderables/renderable_face3.dart'; -part 'src/renderers/renderables/renderable_face4.dart'; part 'src/renderers/renderables/renderable_line.dart'; part 'src/renderers/renderables/renderable_particle.dart';