Add FaceVertexMesh
This commit is contained in:
parent
d846569130
commit
9fd413df2b
@ -13,11 +13,17 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"c = meshutil.cube(open_xz=False)\n",
|
||||
"mesh_fname = \"cube_test.stl\"\n",
|
||||
"c2 = meshutil.cube_distort(0.3)\n",
|
||||
"c2.v = c2.v/2 + [0,1,0]\n",
|
||||
"c = c.concat(c2)\n",
|
||||
"m = c.to_stl_mesh()\n",
|
||||
"\"\"\"\n",
|
||||
"c1 = meshutil.cube_distort(0.3)\n",
|
||||
"c1[\"vectors\"] = c1[\"vectors\"]/2 + [0,1,0]\n",
|
||||
"c2 = meshutil.cube_distort(0.3)\n",
|
||||
@ -25,32 +31,23 @@
|
||||
"c3 = meshutil.cube_distort(0.3)\n",
|
||||
"c3[\"vectors\"] = c3[\"vectors\"]/2 + [0,1,0.5]\n",
|
||||
"c4 = meshutil.cube_distort(0.3)\n",
|
||||
"c4[\"vectors\"] = c4[\"vectors\"]/2 + [0.5,1,0.5]"
|
||||
"c4[\"vectors\"] = c4[\"vectors\"]/2 + [0.5,1,0.5]\n",
|
||||
"\"\"\"\n",
|
||||
"m.save(mesh_fname)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"d = numpy.concatenate([c,c1,c2,c3,c4])"
|
||||
"#d = numpy.concatenate([c,c1,c2,c3,c4])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"mesh = stl.mesh.Mesh(d)\n",
|
||||
"mesh_fname = \"cube_test.stl\"\n",
|
||||
"mesh.save(mesh_fname)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -59,14 +56,16 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"face_normals didn't match triangles, ignoring!\n"
|
||||
"face_normals didn't match triangles, ignoring!\n",
|
||||
"/home/hodapp/.local/lib/python3.6/site-packages/IPython/core/display.py:694: UserWarning: Consider using IPython.display.IFrame instead\n",
|
||||
" warnings.warn(\"Consider using IPython.display.IFrame instead\")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -264,7 +263,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="Z2xURgIAAAA4BwAAsAMAAEpTT057InNjZW5lIjogMCwgInNjZW5lcyI6IFt7Im5vZGVzIjogWzBdfV0sICJhc3NldCI6IHsidmVyc2lvbiI6ICIyLjAiLCAiZ2VuZXJhdG9yIjogImh0dHBzOi8vZ2l0aHViLmNvbS9taWtlZGgvdHJpbWVzaCJ9LCAiYWNjZXNzb3JzIjogW3siYnVmZmVyVmlldyI6IDAsICJjb21wb25lbnRUeXBlIjogNTEyNSwgImNvdW50IjogMTMyLCAibWF4IjogWzI4XSwgIm1pbiI6IFswXSwgInR5cGUiOiAiU0NBTEFSIn0sIHsiYnVmZmVyVmlldyI6IDEsICJjb21wb25lbnRUeXBlIjogNTEyNiwgImNvdW50IjogMjksICJ0eXBlIjogIlZFQzMiLCAiYnl0ZU9mZnNldCI6IDAsICJtYXgiOiBbMS4wLCAxLjc2MjAyMjQ5NTI2OTc3NTQsIDEuMF0sICJtaW4iOiBbLTAuMTcwMDkxODUyNTQ1NzM4MjIsIDAuMCwgLTAuMTcwMDkxODUyNTQ1NzM4MjJdfV0sICJtZXNoZXMiOiBbeyJuYW1lIjogImN1YmVfdGVzdC5zdGwiLCAicHJpbWl0aXZlcyI6IFt7ImF0dHJpYnV0ZXMiOiB7IlBPU0lUSU9OIjogMX0sICJpbmRpY2VzIjogMCwgIm1vZGUiOiA0fV19XSwgImNhbWVyYXMiOiBbeyJuYW1lIjogImNhbWVyYV9VTk5VSVEiLCAidHlwZSI6ICJwZXJzcGVjdGl2ZSIsICJwZXJzcGVjdGl2ZSI6IHsiYXNwZWN0UmF0aW8iOiAxLjMzMzMzMzMzMzMzMzMzMzMsICJ5Zm92IjogMC43ODUzOTgxNjMzOTc0NDgzLCAiem5lYXIiOiAwLjAxfX1dLCAibm9kZXMiOiBbeyJuYW1lIjogIndvcmxkIiwgImNoaWxkcmVuIjogWzFdfSwgeyJuYW1lIjogImN1YmVfdGVzdC5zdGxfVURNTVhVT0RFUjNSIiwgIm1lc2giOiAwfV0sICJidWZmZXJzIjogW3siYnl0ZUxlbmd0aCI6IDg3Nn1dLCAiYnVmZmVyVmlld3MiOiBbeyJidWZmZXIiOiAwLCAiYnl0ZU9mZnNldCI6IDAsICJieXRlTGVuZ3RoIjogNTI4fSwgeyJidWZmZXIiOiAwLCAiYnl0ZU9mZnNldCI6IDUyOCwgImJ5dGVMZW5ndGgiOiAzNDh9XX0gIGwDAABCSU4AAAAAAAcAAAAFAAAAAAAAAAIAAAAHAAAABQAAAAgAAAAGAAAABQAAAAcAAAAIAAAABgAAAAMAAAABAAAABgAAAAgAAAADAAAAAQAAAAIAAAAAAAAAAQAAAAMAAAACAAAAAgAAAAgAAAAHAAAAAgAAAAMAAAAIAAAAAAAAAAUAAAAGAAAAAAAAAAYAAAABAAAAAgAAAAsAAAASAAAAAgAAAA4AAAALAAAAEgAAABgAAAAUAAAAEgAAAAsAAAAYAAAAFAAAABsAAAAEAAAAFAAAABgAAAAbAAAABAAAAA4AAAACAAAABAAAABsAAAAOAAAAEgAAABYAAAAHAAAAEgAAABkAAAAWAAAABwAAAA0AAAAJAAAABwAAABYAAAANAAAACQAAABAAAAAUAAAACQAAAA0AAAAQAAAAFAAAABkAAAASAAAAFAAAABAAAAAZAAAABAAAAAoAAAAUAAAABAAAAA8AAAAKAAAAFAAAABcAAAATAAAAFAAAAAoAAAAXAAAAEwAAABwAAAADAAAAEwAAABcAAAAcAAAAAwAAAA8AAAAEAAAAAwAAABwAAAAPAAAAFAAAABUAAAAJAAAAFAAAABoAAAAVAAAACQAAAAwAAAAIAAAACQAAABUAAAAMAAAACAAAABEAAAATAAAACAAAAAwAAAARAAAAEwAAABoAAAAUAAAAEwAAABEAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAgD8AAAA/AACAPwAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAgD8AAAAAAACAPwAAgD8AAIA/AACAPwAAgD8AAAA/QaGuPiegzj+46ag+QaGuPiegzj+PLC6+GJlRP/SJ4T8YmVE/GJlRP/SJ4T8wMqM+bU4Xvlq2uz9tThe+bU4Xvlq2uz/KWLQ+uOmoPiegzj9Boa4+uOmoPiegzj+gUFc/AAAAPwAAgD8AAAAAAAAAPwAAgD8AAIA/AAAAPwAAgD8AAAA/oFBXPyegzj+46ag+oFBXPyegzj+PLC6+MDKjPvSJ4T8YmVE/MDKjPvSJ4T8wMqM+yli0Plq2uz9tThe+yli0Plq2uz/KWLQ+jywuviegzj9Boa4+jywuviegzj+gUFc/";;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="Z2xURgIAAABwBQAAsAMAAEpTT057InNjZW5lIjogMCwgInNjZW5lcyI6IFt7Im5vZGVzIjogWzBdfV0sICJhc3NldCI6IHsidmVyc2lvbiI6ICIyLjAiLCAiZ2VuZXJhdG9yIjogImh0dHBzOi8vZ2l0aHViLmNvbS9taWtlZGgvdHJpbWVzaCJ9LCAiYWNjZXNzb3JzIjogW3siYnVmZmVyVmlldyI6IDAsICJjb21wb25lbnRUeXBlIjogNTEyNSwgImNvdW50IjogNjAsICJtYXgiOiBbMTRdLCAibWluIjogWzBdLCAidHlwZSI6ICJTQ0FMQVIifSwgeyJidWZmZXJWaWV3IjogMSwgImNvbXBvbmVudFR5cGUiOiA1MTI2LCAiY291bnQiOiAxNSwgInR5cGUiOiAiVkVDMyIsICJieXRlT2Zmc2V0IjogMCwgIm1heCI6IFsxLjAsIDEuNzYyMDIyNDk1MjY5Nzc1NCwgMS4wXSwgIm1pbiI6IFstMC4xNzAwOTE4NTI1NDU3MzgyMiwgMC4wLCAtMC4xNzAwOTE4NTI1NDU3MzgyMl19XSwgIm1lc2hlcyI6IFt7Im5hbWUiOiAiY3ViZV90ZXN0LnN0bCIsICJwcmltaXRpdmVzIjogW3siYXR0cmlidXRlcyI6IHsiUE9TSVRJT04iOiAxfSwgImluZGljZXMiOiAwLCAibW9kZSI6IDR9XX1dLCAiY2FtZXJhcyI6IFt7Im5hbWUiOiAiY2FtZXJhXzBHUVdIQyIsICJ0eXBlIjogInBlcnNwZWN0aXZlIiwgInBlcnNwZWN0aXZlIjogeyJhc3BlY3RSYXRpbyI6IDEuMzMzMzMzMzMzMzMzMzMzMywgInlmb3YiOiAwLjc4NTM5ODE2MzM5NzQ0ODMsICJ6bmVhciI6IDAuMDF9fV0sICJub2RlcyI6IFt7Im5hbWUiOiAid29ybGQiLCAiY2hpbGRyZW4iOiBbMV19LCB7Im5hbWUiOiAiY3ViZV90ZXN0LnN0bF8wVkZQWUxVMENMWFMiLCAibWVzaCI6IDB9XSwgImJ1ZmZlcnMiOiBbeyJieXRlTGVuZ3RoIjogNDIwfV0sICJidWZmZXJWaWV3cyI6IFt7ImJ1ZmZlciI6IDAsICJieXRlT2Zmc2V0IjogMCwgImJ5dGVMZW5ndGgiOiAyNDB9LCB7ImJ1ZmZlciI6IDAsICJieXRlT2Zmc2V0IjogMjQwLCAiYnl0ZUxlbmd0aCI6IDE4MH1dfSAgIKQBAABCSU4AAAAAAAcAAAAFAAAAAAAAAAIAAAAHAAAABQAAAAgAAAAGAAAABQAAAAcAAAAIAAAABgAAAAMAAAABAAAABgAAAAgAAAADAAAAAQAAAAIAAAAAAAAAAQAAAAMAAAACAAAAAgAAAAgAAAAHAAAAAgAAAAMAAAAIAAAAAAAAAAUAAAAGAAAAAAAAAAYAAAABAAAAAgAAAAkAAAALAAAAAgAAAAoAAAAJAAAACwAAAA0AAAAMAAAACwAAAAkAAAANAAAADAAAAA4AAAAEAAAADAAAAA0AAAAOAAAABAAAAAoAAAACAAAABAAAAA4AAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAgD8AAAA/AACAPwAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAgD8AAAAAAACAPwAAgD8AAIA/QaGuPiegzj+PLC6+bU4Xvlq2uz9tThe+AAAAPwAAgD8AAAAAAAAAPwAAgD8AAAA/MDKjPvSJ4T8wMqM+jywuviegzj9Boa4+";;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",
|
||||
@ -275,7 +274,7 @@
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 17,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
||||
88
meshutil.py
88
meshutil.py
@ -16,42 +16,76 @@ rbb = numpy.array([1,0,1])
|
||||
ltb = numpy.array([0,1,1])
|
||||
rtb = numpy.array([1,1,1])
|
||||
|
||||
class FaceVertexMesh(object):
|
||||
def __init__(self, v, f):
|
||||
# v & f should both be of shape (N,3)ll
|
||||
self.v = v
|
||||
self.f = f
|
||||
def concat(self, other_mesh):
|
||||
v2 = numpy.concatenate([self.v, other_mesh.v])
|
||||
# Note index shift!
|
||||
f2 = numpy.concatenate([self.f, other_mesh.f + self.v.shape[0]])
|
||||
m2 = FaceVertexMesh(v2, f2)
|
||||
return m2
|
||||
def to_stl_mesh(self):
|
||||
data = numpy.zeros(self.f.shape[0], dtype=stl.mesh.Mesh.dtype)
|
||||
v = data["vectors"]
|
||||
for i, (iv0, iv1, iv2) in enumerate(self.f):
|
||||
v[i] = [self.v[iv0], self.v[iv1], self.v[iv2]]
|
||||
return stl.mesh.Mesh(data)
|
||||
|
||||
def cube(open_xz=False):
|
||||
verts = numpy.array([
|
||||
lbf, rbf, ltf, rtf,
|
||||
lbb, rbb, ltb, rtb,
|
||||
], dtype=numpy.float32)
|
||||
if open_xz:
|
||||
data = numpy.zeros(8, dtype=stl.mesh.Mesh.dtype)
|
||||
faces = numpy.zeros((8,3), dtype=int)
|
||||
else:
|
||||
data = numpy.zeros(12, dtype=stl.mesh.Mesh.dtype)
|
||||
v = data["vectors"]
|
||||
v[0] = [lbf, rtf, rbf]
|
||||
v[1] = [lbf, ltf, rtf]
|
||||
v[2] = [rbf, rtb, rbb]
|
||||
v[3] = [rbf, rtf, rtb]
|
||||
v[4] = [rbb, ltb, lbb]
|
||||
v[5] = [rbb, rtb, ltb]
|
||||
v[6] = [lbb, ltf, lbf]
|
||||
v[7] = [lbb, ltb, ltf]
|
||||
faces = numpy.zeros((12,3), dtype=int)
|
||||
faces[0,:] = [0, 3, 1]
|
||||
faces[1,:] = [0, 2, 3]
|
||||
faces[2,:] = [1, 7, 5]
|
||||
faces[3,:] = [1, 3, 7]
|
||||
faces[4,:] = [5, 6, 4]
|
||||
faces[5,:] = [5, 7, 6]
|
||||
faces[6,:] = [4, 2, 0]
|
||||
faces[7,:] = [4, 6, 2]
|
||||
if not open_xz:
|
||||
v[8] = [ltf, rtb, rtf]
|
||||
v[9] = [ltf, ltb, rtb]
|
||||
v[10] = [lbf, rbf, rbb]
|
||||
v[11] = [lbf, rbb, lbb]
|
||||
return data
|
||||
faces[8,:] = [2, 7, 3]
|
||||
faces[9,:] = [2, 6, 7]
|
||||
faces[10,:] = [0, 1, 5]
|
||||
faces[11,:] = [0, 5, 4]
|
||||
# winding order?
|
||||
return FaceVertexMesh(verts, faces)
|
||||
|
||||
def cube_distort(angle):
|
||||
data = numpy.zeros(8, dtype=stl.mesh.Mesh.dtype)
|
||||
v = data["vectors"]
|
||||
q = quat.rotation_quaternion(numpy.array([-1,0,1]), angle)
|
||||
ltf2 = quat.conjugate_by(ltf, q)[0,:]
|
||||
rtf2 = quat.conjugate_by(rtf, q)[0,:]
|
||||
ltb2 = quat.conjugate_by(ltb, q)[0,:]
|
||||
rtb2 = quat.conjugate_by(rtb, q)[0,:]
|
||||
# TODO: Just make these functions work right with single vectors
|
||||
v[0] = [lbf, rtf2, rbf]
|
||||
v[1] = [lbf, ltf2, rtf2]
|
||||
v[2] = [rbf, rtb2, rbb]
|
||||
v[3] = [rbf, rtf2, rtb2]
|
||||
v[4] = [rbb, ltb2, lbb]
|
||||
v[5] = [rbb, rtb2, ltb2]
|
||||
v[6] = [lbb, ltf2, lbf]
|
||||
v[7] = [lbb, ltb2, ltf2]
|
||||
return data
|
||||
verts = numpy.array([
|
||||
lbf, rbf, ltf2, rtf2,
|
||||
lbb, rbb, ltb2, rtb2,
|
||||
], dtype=numpy.float32)
|
||||
if True: #open_xz:
|
||||
faces = numpy.zeros((8,3), dtype=int)
|
||||
else:
|
||||
faces = numpy.zeros((12,3), dtype=int)
|
||||
faces[0,:] = [0, 3, 1]
|
||||
faces[1,:] = [0, 2, 3]
|
||||
faces[2,:] = [1, 7, 5]
|
||||
faces[3,:] = [1, 3, 7]
|
||||
faces[4,:] = [5, 6, 4]
|
||||
faces[5,:] = [5, 7, 6]
|
||||
faces[6,:] = [4, 2, 0]
|
||||
faces[7,:] = [4, 6, 2]
|
||||
if False: # not open_xz:
|
||||
faces[8,:] = [2, 7, 3]
|
||||
faces[9,:] = [2, 6, 7]
|
||||
faces[10,:] = [0, 1, 5]
|
||||
faces[11,:] = [0, 5, 4]
|
||||
# winding order?
|
||||
return FaceVertexMesh(verts, faces)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user