Commit 70cd9627 authored by Dario Seyb's avatar Dario Seyb

Added mesh/edge list/point list class to encapsulate geometry + attributes

Meshes can be polygonal, they will get automatically triangulated before
rendering.
Face attributes for polygonal meshes are per polygon and are automatically
associated with the relevant triangles after triangulization.
Meshes with mixed face valence are supported.
See MixedValenceTest for an example.
parent 3a106550
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import meshvis\n",
"import openmesh as om\n",
"import numpy as np\n",
"\n",
"m = om.PolyMesh()\n",
"om.read_mesh(m, 'models/spot_quadrangulated.obj')\n",
"\n",
"vertices = m.points()\n",
"faces = m.face_vertex_indices()\n",
"edges = m.ev_indices()\n",
"\n",
"mesh = meshvis.Mesh(vertices, faces)\n",
"mesh.colors = meshvis.FaceAttribute(np.random.rand(len(faces), 3))\n",
"\n",
"meshvis.Context().draw(mesh).draw(meshvis.EdgeList(vertices, edges)).draw(meshvis.PointList(vertices), point_size=5).display()\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import meshvis\n",
"import openmesh as om\n",
"import numpy as np\n",
"\n",
"m = om.PolyMesh()\n",
"om.read_mesh(m, 'models/spot_quadrangulated.obj')\n",
"\n",
"vertices = m.points()\n",
"faces = m.face_vertex_indices()\n",
"edges = m.ev_indices()\n",
"\n",
"mesh = meshvis.Mesh(vertices, faces)\n",
"mesh.colors = meshvis.FaceAttribute(np.random.rand(len(faces), 3))\n",
"\n",
"meshvis.Context().draw(mesh).draw(meshvis.EdgeList(vertices, edges)).draw(meshvis.PointList(vertices), point_size=5).display()\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
This diff is collapsed.
# Blender v2.79 (sub 0) OBJ File: ''
# www.blender.org
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
s off
f 1//1 2//1 4//1 3//1
f 3//2 4//2 8//2 7//2
f 7//3 8//3 6//3 5//3
f 5//4 6//4 2//4 1//4
f 3//5 7//5 5//5 1//5
f 4//6 6//6 8//6
f 4//6 2//6 6//6
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 0
Ka 0.000000 0.000000 0.000000
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2
# Blender v2.79 (sub 0) OBJ File: ''
# www.blender.org
mtllib cube_quads.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl None
s off
f 1//1 2//1 4//1 3//1
f 3//2 4//2 8//2 7//2
f 7//3 8//3 6//3 5//3
f 5//4 6//4 2//4 1//4
f 3//5 7//5 5//5 1//5
f 8//6 4//6 2//6 6//6
This diff is collapsed.
......@@ -10,4 +10,5 @@ from .context import *
from .immediate import *
from .indexed_attribute import UniformAttribute, PointAttribute, FaceAttribute, HalfEdgeAttribute
from .mesh_helper import *
from .mesh import Mesh, EdgeList, PointList
from pythreejs import ImageTexture, DataTexture
......@@ -6,6 +6,7 @@ from traitlets import link, dlink, Bool
from IPython.display import display
from .indexed_attribute import *
from .mesh_helper import calculateFaceNormals, calculatePointNormals
from .mesh import *
class Context(object):
......@@ -39,11 +40,27 @@ class Context(object):
position=[0, 0, 0])
self.scene.add(mesh_obj)
def draw(self, obj, shading='flat', z_offset=0.5, texture=None, point_size = 1, perspective = False, line_width = 1):
obj.prepare_render()
if isinstance(obj, Mesh):
return self.draw_faces(obj.vertices, obj.tri_face_indices, obj.normals, obj.colors, obj.uvs, shading, z_offset, texture)
elif isinstance(obj, EdgeList):
return self.draw_edges(obj.vertices, obj.edge_indices, obj.colors, obj.uvs, z_offset, texture, line_width)
elif isinstance(obj, PointList):
return self.draw_vertices(obj.vertices, obj.colors, obj.uvs, point_size, z_offset, texture, perspective)
return self
def draw_faces(self, vertices, face_indices, normals=None, colors=None, uvs=None,
shading='flat', z_offset=0.5, texture=None):
assert(len(face_indices) > 0 and len(vertices) > 0)
vertices = np.array(vertices)
face_indices = np.array(face_indices)
......
from .context import *
from .context import Context
def display_faces(vertices, face_indices, normals=None, colors=None, uvs=None,
shading='flat', z_offset=0.5, texture=None, width=600, height=400,
......@@ -14,3 +14,8 @@ def display_vertices(vertices, colors=None, uvs=None, point_size=1, z_offset=0,
perspective=False, width=600, height=400,
background_color = '#dddddd'):
Context(width, height, background_color).draw_vertices(vertices, colors, uvs, point_size, z_offset, texture, perspective).display()
def display(obj, shading='flat', point_size=1, z_offset=0, texture=None,
perspective=False, width=600, height=400,
background_color = '#dddddd'):
Context(width, height, background_color).draw(obj, shading= shading, point_size = point_size, z_offset= z_offset, texture = texture, perspective = perspective).display()
\ No newline at end of file
......@@ -42,6 +42,7 @@ class UniformAttribute(object):
def __init__(self, value):
self.value = value
def resolve(self, face_indices):
result = []
for f_idx, face in enumerate(face_indices):
......@@ -55,6 +56,7 @@ class IndexedAttribute(object):
assert(len(values) == len(indices))
self.values = values
self.indices = indices
self.face_remap = None
class PointAttribute(IndexedAttribute):
def __init__(self, values, indices = None):
......@@ -87,11 +89,16 @@ class FaceAttribute(IndexedAttribute):
def resolve(self, face_indices):
result = []
for i, val in enumerate(self.values):
idx = self.indices[i]
if self.face_remap is None:
self.face_remap = range(len(self.indices))
for i, fidx in enumerate(self.face_remap):
idx = self.indices[fidx]
val = self.values[idx]
# Add value for all vertices in the face
for f_vidx in range(0, len(face_indices[idx])):
result.append((idx, f_vidx, val))
for f_vidx in range(len(face_indices[i])):
result.append((i, f_vidx, val))
return result
......
import numpy as np
from .mesh_helper import calculateFaceNormals, calculatePointNormals
class Mesh():
def __init__(self, vertices, face_indices, normals=None, colors=None, uvs=None):
self.normals = normals
self.colors = colors
self.uvs = uvs
self.face_valence = (face_indices != -1).sum(1)
minValence = self.face_valence.min(axis = 0)
maxValuence = self.face_valence.max(axis = 0)
self.uniform_valence = minValence == maxValuence
self.is_triangulated = self.uniform_valence and self.face_valence[0] == 3
self.vertices = vertices
self.face_indices = face_indices
def prepare_render(self):
if not self.normals:
self.calculateNormals()
self.triangulate()
if self.normals:
self.normals.face_remap = self.triangulate_face_to_attribute_face
if self.colors:
self.colors.face_remap = self.triangulate_face_to_attribute_face
if self.uvs:
self.uvs.face_remap = self.triangulate_face_to_attribute_face
def calculateNormals(self, normal_element = 'face'):
assert(normal_element is 'face' or normal_element is 'point')
if normal_element is 'face':
self.normals = calculateFaceNormals(self.vertices, self.face_indices)
else:
self.normals = calculatePointNormals(self.vertices, self.face_indices)
def triangulate(self):
if self.is_triangulated:
self.tri_face_indices = self.face_indices
self.triangulate_face_to_attribute_face = np.range(len(self.face_indices))
return
new_faces = []
triangulate_face_to_attribute_face = []
for fid, face in enumerate(self.face_indices):
originVertex = face[0]
for in_face_idx in range(2, self.face_valence[fid]):
triangulate_face_to_attribute_face.append(fid)
new_faces.append([originVertex, face[in_face_idx-1], face[in_face_idx]])
self.triangulate_face_to_attribute_face = np.array(triangulate_face_to_attribute_face)
self.tri_face_indices = np.array(new_faces)
self.is_triangulated = True
class PointList():
def __init__(self, vertices, colors = None, uvs = None):
self.vertices = vertices
self.colors = colors
self.uvs = uvs
def prepare_render(self):
pass
class EdgeList():
def __init__(self, vertices, edge_indices, colors=None, uvs=None):
self.vertices = vertices
self.edge_indices = edge_indices
self.colors = colors
self.uvs = uvs
def prepare_render(self):
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment