From 1113c6d137566e0c4ff2e40d22e416ce8ed5ba11 Mon Sep 17 00:00:00 2001 From: Thomas FORGIONE Date: Wed, 18 Jan 2017 10:27:34 +0100 Subject: [PATCH] ply ascii parser supports vertex colors --- assets/shaders/shader.frag | 3 ++- assets/shaders/shader.vert | 2 ++ d3/model/basemodel.py | 20 ++++++++++++----- d3/model/formats/ply.py | 44 ++++++++++++++++++++++++++++++++++---- d3/model/mesh.py | 21 ++++++++++++++++-- 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/assets/shaders/shader.frag b/assets/shaders/shader.frag index 03bc4fe..b850034 100644 --- a/assets/shaders/shader.frag +++ b/assets/shaders/shader.frag @@ -1,4 +1,5 @@ varying vec3 fNormal; +varying vec4 fFrontColor; vec3 ambientLight = vec3(0.2,0.2,0.2); vec3 directionnalLight = normalize(vec3(10,5,7)); @@ -15,7 +16,7 @@ void main() { vec4 color = texture2D(tex, gl_TexCoord[0].st); vec4 fragColor = noTexColor * color; - gl_FragColor = fragColor; + gl_FragColor = fragColor * fFrontColor; } diff --git a/assets/shaders/shader.vert b/assets/shaders/shader.vert index e63abfb..a50f4ef 100644 --- a/assets/shaders/shader.vert +++ b/assets/shaders/shader.vert @@ -1,10 +1,12 @@ varying vec3 fNormal; varying vec4 fTexCoord; +varying vec4 fFrontColor; void main() { fNormal = gl_Normal; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + fFrontColor = gl_Color; } diff --git a/d3/model/basemodel.py b/d3/model/basemodel.py index 35db913..b241af2 100644 --- a/d3/model/basemodel.py +++ b/d3/model/basemodel.py @@ -3,8 +3,9 @@ from ..geometry import Vector from .mesh import Material, MeshPart Vertex = Vector -Normal = Vertex TexCoord = Vertex +Normal = Vertex +Color = Vertex class FaceVertex: """Contains the information a vertex needs in a face @@ -12,12 +13,13 @@ class FaceVertex: In contains the index of the vertex, the index of the texture coordinate and the index of the normal. It is None if it is not available. """ - def __init__(self, vertex = None, tex_coord = None, normal = None): + def __init__(self, vertex = None, tex_coord = None, normal = None, color = None): """Initializes a FaceVertex from its indices """ self.vertex = vertex self.tex_coord = tex_coord self.normal = normal + self.color = color def from_array(self, arr): """Initializes a FaceVertex from an array @@ -38,6 +40,11 @@ class FaceVertex: except: self.normal = None + try: + self.color = int(arr[3]) if len(arr) > 3 else None + except: + self.color = None + return self class Face: @@ -75,15 +82,13 @@ class ModelParser: """ self.up_conversion = up_conversion self.vertices = [] + self.colors = [] self.normals = [] self.tex_coords = [] self.parts = [] self.current_part = None self.bounding_box = BoundingBox() self.center_and_scale = True - self.vertex_vbo = None - self.tex_coord_vbo = None - self.normal_vbo = None self.path = None def init_textures(self): @@ -121,6 +126,11 @@ class ModelParser: """ self.normals.append(normal) + def add_color(self, color): + """Adds a color element to the current model + """ + self.colors.append(color) + def add_face(self, face): """Adds a face to the current model diff --git a/d3/model/formats/ply.py b/d3/model/formats/ply.py index befa5f5..11a12d1 100644 --- a/d3/model/formats/ply.py +++ b/d3/model/formats/ply.py @@ -2,7 +2,7 @@ import os import sys import PIL import struct -from ..basemodel import ModelParser, TextModelParser, Exporter, Vertex, Face, FaceVertex, TexCoord, Material +from ..basemodel import ModelParser, TextModelParser, Exporter, Vertex, Face, Color, FaceVertex, TexCoord, Material class UnkownTypeError(Exception): def __init__(self, message): @@ -172,9 +172,42 @@ class PLY_ASCII_ContentParser: self.current_element = self.parent.elements[0] split = string.split() + color = None if self.current_element.name == 'vertex': - self.parent.add_vertex(Vertex().from_array(split)) + + vertex = Vertex() + red = None + blue = None + green = None + alpha = None + + offset = 0 + for property in self.current_element.properties: + + if property[0] == 'x': + vertex.x = float(split[offset]) + elif property[0] == 'y': + vertex.y = float(split[offset]) + elif property[0] == 'z': + vertex.z = float(split[offset]) + elif property[0] == 'red': + red = float(split[offset]) / 255 + elif property[0] == 'green': + green = float(split[offset]) / 255 + elif property[0] == 'blue': + blue = float(split[offset]) / 255 + elif property[0] == 'alpha': + alpha = float(split[offset]) / 255 + + offset += 1 + + self.parent.add_vertex(vertex) + + if red is not None: + color = Color(red, blue, green) + self.parent.add_color(color) + elif self.current_element.name == 'face': faceVertexArray = [] @@ -183,10 +216,12 @@ class PLY_ASCII_ContentParser: # Analyse element offset = 0 for property in self.current_element.properties: + if property[0] == 'vertex_indices': for i in range(int(split[offset])): faceVertexArray.append(FaceVertex(int(split[i+offset+1]))) offset += int(split[0]) + 1 + elif property[0] == 'texcoord': offset += 1 for i in range(3): @@ -195,6 +230,7 @@ class PLY_ASCII_ContentParser: offset += 2 self.parent.add_tex_coord(tex_coord) faceVertexArray[i].tex_coord = len(self.parent.tex_coords) - 1 + elif property[0] == 'texnumber': current_material = self.parent.materials[int(split[offset])] @@ -314,8 +350,8 @@ class PLYLittleEndianContentParser: elif property[0] == 'texnumber': material = self.parent.materials[property_values[i]] - for tex_coord in tex_coords: - self.parent.add_tex_coord(tex_coord) + for tex_coord in tex_coords: + self.parent.add_tex_coord(tex_coord) face = Face(*list(map(lambda x: FaceVertex(x), vertex_indices))) diff --git a/d3/model/mesh.py b/d3/model/mesh.py index 54d6ff3..1cd9d6a 100644 --- a/d3/model/mesh.py +++ b/d3/model/mesh.py @@ -24,7 +24,6 @@ class Material: try: ix, iy, image = self.map_Kd.size[0], self.map_Kd.size[1], self.map_Kd.tobytes("raw", "RGBA", 0, -1) except: - print('Humm') ix, iy, image = self.map_Kd.size[0], self.map_Kd.size[1], self.map_Kd.tobytes("raw", "RGBX", 0, -1) self.id = gl.glGenTextures(1) @@ -59,7 +58,7 @@ Material.DEFAULT_MATERIAL.Ks = 0.0 try: import PIL.Image Material.DEFAULT_MATERIAL.map_Kd = PIL.Image.new("RGBA", (1,1), "white") -except: +except ImportError: pass class MeshPart: @@ -69,6 +68,7 @@ class MeshPart: self.vertex_vbo = None self.tex_coord_vbo = None self.normal_vbo = None + self.color_vbo = None self.faces = [] def init_texture(self): @@ -87,6 +87,7 @@ class MeshPart: v = [] n = [] t = [] + c = [] for face in self.faces: v1 = self.parent.vertices[face.a.vertex] @@ -106,6 +107,12 @@ class MeshPart: t3 = self.parent.tex_coords[face.c.tex_coord] t += [[t1.x, t1.y], [t2.x, t2.y], [t3.x, t3.y]] + if len(self.parent.colors) > 0: # face.a.color is not None: + c1 = self.parent.colors[face.a.vertex] + c2 = self.parent.colors[face.b.vertex] + c3 = self.parent.colors[face.c.vertex] + c += [[c1.x, c1.y, c1.z], [c2.x, c2.y, c2.z], [c3.x, c3.y, c3.z]] + self.vertex_vbo = vbo.VBO(array(v, 'f')) if len(n) > 0: @@ -114,6 +121,9 @@ class MeshPart: if len(t) > 0: self.tex_coord_vbo = vbo.VBO(array(t, 'f')) + if len(c) > 0: + self.color_vbo = vbo.VBO(array(c, 'f')) + def draw(self): if self.material is not None: @@ -152,11 +162,18 @@ class MeshPart: gl.glTexCoordPointerf(self.tex_coord_vbo) self.tex_coord_vbo.unbind() + if self.color_vbo is not None: + self.color_vbo.bind() + gl.glEnableClientState(gl.GL_COLOR_ARRAY) + gl.glColorPointerf(self.color_vbo) + self.color_vbo.unbind() + gl.glDrawArrays(gl.GL_TRIANGLES, 0, len(self.vertex_vbo.data) * 9) gl.glDisableClientState(gl.GL_VERTEX_ARRAY) gl.glDisableClientState(gl.GL_NORMAL_ARRAY) gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY) + gl.glDisableClientState(gl.GL_COLOR_ARRAY) def draw_from_arrays(self):