From d6f6edc8a8f3fa19c482afe39aad6b667364b780 Mon Sep 17 00:00:00 2001 From: Chris Hodapp Date: Sat, 28 Sep 2019 04:04:22 +0200 Subject: [PATCH] First example of actual 3D recursive shape! --- Scratch.ipynb | 115 +++++++++++++++++++------------------------------- meshutil.py | 15 ++++++- 2 files changed, 58 insertions(+), 72 deletions(-) diff --git a/Scratch.ipynb b/Scratch.ipynb index bb1db6a..f9f9a30 100644 --- a/Scratch.ipynb +++ b/Scratch.ipynb @@ -18,13 +18,14 @@ "metadata": {}, "outputs": [], "source": [ - "b1 = numpy.array([\n", + "b0 = numpy.array([\n", " [0, 0, 0],\n", " [1, 0, 0],\n", " [1, 1, 0],\n", " [0, 1, 0],\n", - "], dtype=numpy.float64) - 0.5\n", - "b2 = numpy.array(b1 + [0,0,1])" + "], dtype=numpy.float64) - [0.5, 0.5, 0]\n", + "xf0_to_1 = meshutil.Transform().translate(0,0,1)\n", + "b1 = xf0_to_1.apply_to(b0)" ] }, { @@ -32,60 +33,57 @@ "execution_count": 7, "metadata": {}, "outputs": [], - "source": [ - "ang = 0.15\n", - "xform = meshutil.Transform().translate(0,0,0.5)\n", - "\n", - "mesh = meshutil.join_boundary_simple(b1, b2)\n", - "for i,bound in enumerate(meshutil.subdivide_boundary(b2)):\n", - " m = xform.apply_to(bound) #xform.rotate([0,0,1], i*numpy.pi/2).apply_to(bound)\n", - " mesh = mesh.concat(meshutil.join_boundary_simple(bound, m))\n", - "\n", - "# One problem: without an actual transform in subdivide_boundary,\n", - "# the transforms aren't inherited, and there is no transformed space.\n", - "# I'm just dealing directly with transformed geometry.\n", - "#\n", - "# My rotation around z in the loop above won't work the way I intended.\n", - "#\n", - "# In other words: I don't need to subdivide *geometry*.\n", - "# I need to subdivide *space* and then put geometry in it.\n", - "\n", - "mesh.to_stl_mesh().save(\"simple.stl\")" - ] - }, - { - "cell_type": "code", - "execution_count": 65, - "metadata": {}, - "outputs": [], "source": [ "mesh_fname = \"cube_test.stl\"\n", "\n", - "# center at (0,0,0) for sanity reasons\n", - "center = meshutil.Transform().translate(-0.5, -0.5, -0.5)\n", - "base = meshutil.cube(open_xz=False).transform(center)\n", - "\n", - "xform = center.translate(-0.5,1.5,-0.5).scale(0.5)\n", - "ang = 0.15\n", - "l2 = meshutil.cube_distort(ang, open_xz=False)\n", - "\n", - "mesh = base\n", - "for layer in range(2):\n", - " for i in range(4):\n", - " m = l2.transform(xform.rotate([0,1,0], i*numpy.pi/2))\n", + "mesh = meshutil.join_boundary_simple(b0, b1)\n", + "mesh = mesh.concat(meshutil.close_boundary_simple(b0))\n", + "for i in range(4):\n", + " # Opening boundary:\n", + " b = b1\n", + " xf = meshutil.Transform() \\\n", + " .translate(0,0,-1) \\\n", + " .scale(0.5) \\\n", + " .translate(0.25,0.25,1) \\\n", + " .rotate([0,0,1], i*numpy.pi/2)\n", + " for layer in range(30):\n", + " b_sub0 = xf.apply_to(b)\n", + " incr = meshutil.Transform() \\\n", + " .scale(0.9) \\\n", + " .rotate([-1,0,1], 0.3) \\\n", + " .translate(0,0,0.8)\n", + " b_sub1 = incr.compose(xf).apply_to(b)\n", + " m = meshutil.join_boundary_simple(b_sub0, b_sub1)\n", " mesh = mesh.concat(m)\n", - " xform = xform.rotate([-1,0,1], ang).scale(1.0).translate(0, 0.7, 0)\n", + " xf = incr.compose(xf)\n", + " # Close final boundary:\n", + " mesh = mesh.concat(meshutil.close_boundary_simple(b_sub1[::-1,:]))\n", + " # ::-1 is to reverse the boundary's order to fix winding order.\n", + " # Not sure of the \"right\" way to fix winding order here.\n", + " # The boundary vertices go in an identical order... it's just\n", + " # that clockwise/counter-clockwise flip.\n", + "\n", + "# I keep confusing the 'incremental' transform with the\n", + "# transform to get b_open in the first place\n", + " \n", + "# rotate([-1,0,1], ang).rotate([0,0,1], i*numpy.pi/2)\n", + "\n", + "# I don't need to subdivide *geometry*.\n", + "# I need to subdivide *space* and then put geometry in it.\n", "\n", "# Work around some annoying-ass trimesh/threejs bug:\n", "wtf = meshutil.Transform().scale(0.1).translate(5,0,0)\n", + "center = meshutil.Transform().translate(-0.5, -0.5, -0.5)\n", + "base = meshutil.cube(open_xz=False).transform(center)\n", "base = base.transform(wtf)\n", - "mesh = mesh.concat(base)\n", + "# to enable:\n", + "#mesh = mesh.concat(base)\n", "mesh.to_stl_mesh().save(mesh_fname)" ] }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -290,7 +288,7 @@ "Math.pow(distanceToCamera,2)+\n", "Math.pow(distanceToCamera,2));camera.position.set(len,len,len);controls.update();camera.lookAt(boundingSphere.center);controls.target.set(boundingSphere.center.x,boundingSphere.center.y,boundingSphere.center.z);camera.updateProjectionMatrix();}\n", "function centerControls(obj,camera,controls){const boundingBox=new THREE.Box3().setFromObject(obj);const boundingSphere=new THREE.Sphere();boundingBox.getBoundingSphere((target=boundingSphere));controls.update();controls.target.set(boundingSphere.center.x,boundingSphere.center.y,boundingSphere.center.z);}\n", - "function init(){scene=new THREE.Scene();scene.background=new THREE.Color(0xffffff);tracklight=new THREE.DirectionalLight(0xffffff,1.75);scene.add(tracklight);base64_data="Z2xURgIAAADIDAAA0AMAAEpTT057InNjZW5lIjogMCwgInNjZW5lcyI6IFt7Im5vZGVzIjogWzBdfV0sICJhc3NldCI6IHsidmVyc2lvbiI6ICIyLjAiLCAiZ2VuZXJhdG9yIjogImh0dHBzOi8vZ2l0aHViLmNvbS9taWtlZGgvdHJpbWVzaCJ9LCAiYWNjZXNzb3JzIjogW3siYnVmZmVyVmlldyI6IDAsICJjb21wb25lbnRUeXBlIjogNTEyNSwgImNvdW50IjogMzYwLCAibWF4IjogWzY4XSwgIm1pbiI6IFswXSwgInR5cGUiOiAiU0NBTEFSIn0sIHsiYnVmZmVyVmlldyI6IDEsICJjb21wb25lbnRUeXBlIjogNTEyNiwgImNvdW50IjogNjksICJ0eXBlIjogIlZFQzMiLCAiYnl0ZU9mZnNldCI6IDAsICJtYXgiOiBbNS4wNTAwMDAxOTA3MzQ4NjMsIDEuNzkwNTQyODQwOTU3NjQxNiwgMC43MzIyOTE5MzY4NzQzODk2XSwgIm1pbiI6IFstMC43MzIyOTE5MzY4NzQzODk2LCAtMC41LCAtMC43MzIyOTE5MzY4NzQzODk2XX1dLCAibWVzaGVzIjogW3sibmFtZSI6ICJjdWJlX3Rlc3Quc3RsIiwgInByaW1pdGl2ZXMiOiBbeyJhdHRyaWJ1dGVzIjogeyJQT1NJVElPTiI6IDF9LCAiaW5kaWNlcyI6IDAsICJtb2RlIjogNH1dfV0sICJjYW1lcmFzIjogW3sibmFtZSI6ICJjYW1lcmFfRVhYN0dLIiwgInR5cGUiOiAicGVyc3BlY3RpdmUiLCAicGVyc3BlY3RpdmUiOiB7ImFzcGVjdFJhdGlvIjogMS4zMzMzMzMzMzMzMzMzMzMzLCAieWZvdiI6IDAuNzg1Mzk4MTYzMzk3NDQ4MywgInpuZWFyIjogMC4wMX19XSwgIm5vZGVzIjogW3sibmFtZSI6ICJ3b3JsZCIsICJjaGlsZHJlbiI6IFsxXX0sIHsibmFtZSI6ICJjdWJlX3Rlc3Quc3RsX0VOV1NNOE5NTkpKSSIsICJtZXNoIjogMH1dLCAiYnVmZmVycyI6IFt7ImJ5dGVMZW5ndGgiOiAyMjY4fV0sICJidWZmZXJWaWV3cyI6IFt7ImJ1ZmZlciI6IDAs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";;renderer=new THREE.WebGLRenderer({antialias:true});renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);loader=new THREE.GLTFLoader();loader.load("data:text/plain;base64,"+base64_data,function(gltf){scene.add(gltf.scene);camera=gltf.cameras[0];controls=new THREE.TrackballControls(camera);controls.rotateSpeed=1.0;controls.zoomSpeed=1.2;controls.panSpeed=0.8;controls.noZoom=false;controls.noPan=false;controls.staticMoving=true;controls.dynamicDampingFactor=0.3;controls.keys=[65,83,68];controls.addEventListener("change",render);centerControls(scene,camera,controls);render();window.addEventListener("resize",onWindowResize,false);animate();});}\n", + "function init(){scene=new THREE.Scene();scene.background=new THREE.Color(0xffffff);tracklight=new THREE.DirectionalLight(0xffffff,1.75);scene.add(tracklight);base64_data="Z2xURgIAAABUMwAA1AMAAEpTT057InNjZW5lIjogMCwgInNjZW5lcyI6IFt7Im5vZGVzIjogWzBdfV0sICJhc3NldCI6IHsidmVyc2lvbiI6ICIyLjAiLCAiZ2VuZXJhdG9yIjogImh0dHBzOi8vZ2l0aHViLmNvbS9taWtlZGgvdHJpbWVzaCJ9LCAiYWNjZXNzb3JzIjogW3siYnVmZmVyVmlldyI6IDAsICJjb21wb25lbnRUeXBlIjogNTEyNSwgImNvdW50IjogMjAxOSwgIm1heCI6IFszMzddLCAibWluIjogWzBdLCAidHlwZSI6ICJTQ0FMQVIifSwgeyJidWZmZXJWaWV3IjogMSwgImNvbXBvbmVudFR5cGUiOiA1MTI2LCAiY291bnQiOiAzMzgsICJ0eXBlIjogIlZFQzMiLCAiYnl0ZU9mZnNldCI6IDAsICJtYXgiOiBbMS4zMjE1Nzc5MDY2MDg1ODE1LCAxLjMyMTU3NzkwNjYwODU4MTUsIDIuNTczMTk5MDMzNzM3MTgyNl0sICJtaW4iOiBbLTEuMzIxNTc3OTA2NjA4NTgxNSwgLTEuMzIxNTc3OTA2NjA4NTgxNSwgMC4wXX1dLCAibWVzaGVzIjogW3sibmFtZSI6ICJjdWJlX3Rlc3Quc3RsIiwgInByaW1pdGl2ZXMiOiBbeyJhdHRyaWJ1dGVzIjogeyJQT1NJVElPTiI6IDF9LCAiaW5kaWNlcyI6IDAsICJtb2RlIjogNH1dfV0sICJjYW1lcmFzIjogW3sibmFtZSI6ICJjYW1lcmFfWTNRQU9CIiwgInR5cGUiOiAicGVyc3BlY3RpdmUiLCAicGVyc3BlY3RpdmUiOiB7ImFzcGVjdFJhdGlvIjogMS4zMzMzMzMzMzMzMzMzMzMzLCAieWZvdiI6IDAuNzg1Mzk4MTYzMzk3NDQ4MywgInpuZWFyIjogMC4wMX19XSwgIm5vZGVzIjogW3sibmFtZSI6ICJ3b3JsZCIsICJjaGlsZHJlbiI6IFsxXX0sIHsibmFtZSI6ICJjdWJlX3Rlc3Quc3RsX1pIUU9IQjNGT0hWUCIsICJtZXNoIjogMH1dLCAiYnVmZmVycyI6IFt7ImJ5dGVMZW5ndGgiOiAxMjEzMn1dLCAiYnVmZmVyVmlld3MiOiBbeyJidWZmZXIi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";;renderer=new THREE.WebGLRenderer({antialias:true});renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);loader=new THREE.GLTFLoader();loader.load("data:text/plain;base64,"+base64_data,function(gltf){scene.add(gltf.scene);camera=gltf.cameras[0];controls=new THREE.TrackballControls(camera);controls.rotateSpeed=1.0;controls.zoomSpeed=1.2;controls.panSpeed=0.8;controls.noZoom=false;controls.noPan=false;controls.staticMoving=true;controls.dynamicDampingFactor=0.3;controls.keys=[65,83,68];controls.addEventListener("change",render);centerControls(scene,camera,controls);render();window.addEventListener("resize",onWindowResize,false);animate();});}\n", "function onWindowResize(){camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);controls.handleResize();render();}\n", "function animate(){requestAnimationFrame(animate);controls.update();}\n", "function render(){tracklight.position.copy(camera.position);renderer.render(scene,camera);}\n", @@ -301,7 +299,7 @@ "" ] }, - "execution_count": 66, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -311,34 +309,9 @@ "m = trimesh.load_mesh(mesh_fname)\n", "#m.show()\n", "scene = trimesh.Scene([m])\n", - "# Seems to do nothing:\n", - "# scene.camera_transform = scene.camera.look_at(m.vertices, distance=10)\n", "scene.show()" ] }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[ 1. , 0. , 0. , -0.07059288],\n", - " [ 0. , 1. , 0. , 0.09608653],\n", - " [-0. , 0. , 1. , 2.14795328],\n", - " [ 0. , 0. , 0. , 1. ]])" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "scene.camera_transform" - ] - }, { "cell_type": "code", "execution_count": null, diff --git a/meshutil.py b/meshutil.py index 2e20c39..98c09cd 100644 --- a/meshutil.py +++ b/meshutil.py @@ -46,6 +46,8 @@ class Transform(object): def _compose(self, mtx2): # Note pre-multiply. Earlier transforms are done first. return Transform(mtx2 @ self.mtx) + def compose(self, xform): + return self._compose(xform.mtx) def scale(self, *a, **kw): return self._compose(mtx_scale(*a, **kw)) def translate(self, *a, **kw): @@ -160,7 +162,7 @@ def join_boundary_simple(bound1, bound2): # simply connecting quads (made of 2 triangles) straight across. # # Winding will proceed in the direction of the first boundary. - #` + # # Returns FaceVertexMesh. n = bound1.shape[0] vs = numpy.concatenate([bound1, bound2]) @@ -172,3 +174,14 @@ def join_boundary_simple(bound1, bound2): fs[2*i] = [n + v1, n + v0, v0] fs[2*i + 1] = [v1, n + v1, v0] return FaceVertexMesh(vs, fs) + +def close_boundary_simple(bound): + # This will fail for any non-convex boundary! + centroid = numpy.mean(bound, axis=0) + vs = numpy.concatenate([bound, centroid[numpy.newaxis,:]]) + n = bound.shape[0] + # note that n is new the index of the centroid + fs = numpy.zeros((n+1, 3), dtype=int) + for i in range(n): + fs[i] = [i, n, (i+1) % n] + return FaceVertexMesh(vs, fs)