#!BPY """ Name: 'GMesh file (.pos)...' Blender: 243 Tooltip: 'Vizulaize a GMesh POS File.' """ __author__= "Jiri Hnidek" __url__= ["blender", "blenderartist"] __version__= "0.2" __bpydoc__= """\ This script imports GMesh pos 1.0 files to Blender and visualize it. Usage: """ # $Id:$ # # -------------------------------------------------------------------------- # POS GMESH Import v1.1 by Jiri Hnidek # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- def hsv_to_rgb(h, s, v): """Converts hsv color to rgb color""" f = p = q = t = 0.0 if h>1.0: h = 1.0 elif h<0.0: h = 0.0 h = 360.0*h if s==0: r = v g = v b = v else: if h==360.0: h = 0.0 h = h/60.0 i = int(h) f = h - float(i) p = v*(1.0 - s) q = v*(1.0 - (s*f)) t = v*(1.0 - (s*(1.0 - f))) if i==0: r = v g = t b = p elif i==1: r = q g = v b = p elif i==2: r = p g = v b = t elif i==3: r = p g = q b = v elif i==4: r = t g = p b = v elif i==5: r = v g = p b = q return r, g, b from Blender import * from Blender.Mathutils import * import math class value_id: def __init__(self, id): self.id = id self.max = -1.7e38 self.min = 1.7e38 def min_max(self, value): if self.max < value: self.max = value if self.min > value: self.min = value class vis_point: bb = [1.7e38, 1.7e38, 1.7e38, -1.7e38, -1.7e38, -1.7e38] val_ids = {} vect_ids = {} def __init__(self, x, y, z, index): self.co = Vector([x, y, z]) self.vals = {} self.vectors = {} self.id = index # bounding box if xvis_point.bb[3]: vis_point.bb[3]=x if yvis_point.bb[4]: vis_point.bb[4]=y if zvis_point.bb[5]: vis_point.bb[2]=z def add_value(self, id, value): self.vals[id] = value try: vis_point.val_ids[id] except: vis_point.val_ids[id] = value_id(id) vis_point.val_ids[id].min_max(value) def add_vector(self, id, vector): self.vectors[id] = vector try: vis_point.vect_ids[id] except: vis_point.vect_ids[id] = value_id(id) vis_point.vect_ids[id].min_max(vector.length) class vis_triangle: def __init__(self, p1, p2, p3, index): self.p1 = p1 self.p2 = p2 self.p3 = p3 self.id = index self.count = 0 class vis_quat: def __init__(self, p1, p2, p3, p4, index): self.p1 = p1 self.p2 = p2 self.p3 = p3 self.p4 = p4 self.id = index class vis_simplex: def __init__(self, t1, t2, t3, t4): self.t1 = t1; self.t2 = t2 self.t3 = t3 self.t4 = t4 class vis_vector: def __init__(self, x, y, z): self.vec = Vector([x, y, z]) self.length = math.sqrt(x*x + y*y + z*z) # classes for GUI class scalar_data: count = 100 def __init__(self, name, layer, min_v, max_v, sel): self.name = name self.layer = layer self.min = min_v self.max = max_v self.selected = sel self.id = scalar_data.count scalar_data.count += 1 class vector_data: count = 10000 def __init__(self, name, object, sel): self.name = name self.object = object self.selected = sel self.id = vector_data.count vector_data.count += 1 class gui_data: # data encapsulating data for gui def __init__(self): # file name self.file_name = "" # list of scalars self.scalar_data_list = [] self.min_scalar_value = "" self.max_scalar_value = "" # list of vectors self.vector_data_list = [] self.min_vector_value = "" self.max_vector_value = "" class vis_data: # data encapsulating visualized data def __init__(self, name): # internal data self.name = name self.points = {} self.point_index = 0 self.triangles = {} self.triangle_index = 0 self.simplexes = [] # temporary data for volume data (stored in one mesh object) self.verts = [] self.faces = [] # temporary vector data (stored in multiple mesh objects) self.edges = [] # blender data self.objects = [] self.meshes = [] self.base_mesh = None self.base_object = None self.scene = None # gui data self.gui = gui_data() def import_point(self, x, y, z): try: point = self.points[x,y,z] except: point = vis_point(x,y,z, self.point_index) self.point_index += 1 self.points[x,y,z] = point self.verts.append(point.co) return point def import_triangle(self, id, x1, y1, z1, x2, y2, z2, x3, y3, z3, val1, val2, val3): p1 = self.import_point(x1, y1, z1) p1.add_value(id, val1) p2 = self.import_point(x2, y2, z2) p2.add_value(id, val2) p3 = self.import_point(x3, y3, z3) p3.add_value(id, val3) p_hash = [p1, p2, p3] p_hash.sort() p_hash = tuple(p_hash) try: triangle = self.triangles[p_hash] except: triangle = vis_triangle(p1, p2, p3, self.triangle_index) self.triangle_index += 1 self.triangles[p_hash] = triangle self.faces.append([p1.id, p2.id, p3.id]) triangle.count += 1 return triangle def import_simplex(self, id, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, val1, val2, val3, val4): t1 = self.import_triangle(id, x1, y1, z1, x2, y2, z2, x3, y3, z3, val1, val2, val3) t2 = self.import_triangle(id, x1, y1, z1, x2, y2, z2, x4, y4, z4, val1, val2, val4) t3 = self.import_triangle(id, x2, y2, z2, x3, y3, z3, x4, y4, z4, val2, val3, val4) t4 = self.import_triangle(id, x3, y3, z3, x1, y1, z1, x4, y4, z4, val3, val1, val4) simplex = vis_simplex(t1, t2, t3, t4) self.simplexes.append(simplex) return simplex def import_vector(self, id, x, y, z, dx, dy, dz): vector = vis_vector(dx, dy, dz) p = self.import_point(x, y, z) p.add_vector(id, vector) return vector def add_surface_data(self): pass def add_volume_data(self): self.base_mesh.verts.extend(self.verts) self.base_mesh.faces.extend(self.faces) # make bindings between vertexes and vis_points for point in self.points.values(): point.vert = self.base_mesh.verts[point.id] # make bindings between faces and vis_triangles for triangle in self.triangles.values(): triangle.face = self.base_mesh.faces[triangle.id] if len(self.points.values()) > 0: # value_ids are stored in points value_ids = self.points.values()[0].val_ids.keys() else: value_ids = [] for value_id in value_ids: # create new vertex color layer self.base_mesh.addColorLayer(value_id) self.base_mesh.activeColorLayer = value_id # min and max values of current layer min_v = self.points.values()[0].val_ids[value_id].min max_v = self.points.values()[0].val_ids[value_id].max # add vertex colors to this layer for triangle in self.triangles.values(): # 1st vertex val = 1.0 - 0.83*((float(triangle.p1.vals[value_id])-min_v)/(max_v-min_v))-0.17 r, g, b = hsv_to_rgb(val, 1.0, 1.0) self.base_mesh.faces[triangle.id].col[0].r = int(255.0*r) self.base_mesh.faces[triangle.id].col[0].g = int(255.0*g) self.base_mesh.faces[triangle.id].col[0].b = int(255.0*b) # 2nd vertex val = 1.0 - 0.83*((float(triangle.p2.vals[value_id])-min_v)/(max_v-min_v))-0.17 r, g, b = hsv_to_rgb(val, 1.0, 1.0) self.base_mesh.faces[triangle.id].col[1].r = int(255.0*r) self.base_mesh.faces[triangle.id].col[1].g = int(255.0*g) self.base_mesh.faces[triangle.id].col[1].b = int(255.0*b) # 3rd vertex val = 1.0 - 0.83*((float(triangle.p3.vals[value_id])-min_v)/(max_v-min_v))-0.17 r, g, b = hsv_to_rgb(val, 1.0, 1.0) self.base_mesh.faces[triangle.id].col[2].r = int(255.0*r) self.base_mesh.faces[triangle.id].col[2].g = int(255.0*g) self.base_mesh.faces[triangle.id].col[2].b = int(255.0*b) self.base_mesh.update() def add_vectors(self): if len(self.points.values()) > 0: # get sizes of bounding box stored in points dx = self.points.values()[0].bb[3] - self.points.values()[0].bb[0] dy = self.points.values()[0].bb[4] - self.points.values()[0].bb[1] dz = self.points.values()[0].bb[5] - self.points.values()[0].bb[2] # maximal bb size max_bb = max([dx, dy, dz]) # list of vector IDs vect_ids = self.points.values()[0].vect_ids.keys() else: vect_ids = [] dx = dy = dz = max_bb = 0 for vect_id in vect_ids: # add object for adding edges(vectors) vect_object = Object.New('Mesh') vect_object.setName(vect_id) vect_mesh = Mesh.New(vect_id) vect_object.link(vect_mesh) # make all vector objects x-ray objects vect_object.setDrawMode(Object.DrawModes.XRAY) self.objects.append(vect_object) self.scene.link(vect_object) # make base object parent of all vector objects self.base_object.makeParent([vect_object]) # add edges to current object verts = [] edges = [] i = 0 # max/min vector size max_vect_size = self.points.values()[0].vect_ids[vect_id].max min_vect_size = self.points.values()[0].vect_ids[vect_id].min k = (max_vect_size/(max_bb/5) - 1)/(max_vect_size - min_vect_size) for point in self.points.values(): if len(point.vectors)>0: try: vec = point.vectors[vect_id].vec except: continue verts.append(point.co) # factor of division of vector length fact = k*point.vectors[vect_id].length + 1 verts.append(point.co + vec/fact) edges.append([i, i+1]) i += 2 vect_mesh.verts.extend(verts) vect_mesh.edges.extend(edges) vect_mesh.update() def add_blender_data(self): self.add_surface_data() self.add_volume_data() self.add_vectors() def add_blender_mesh(self): self.base_mesh = Mesh.New(self.name) def add_blender_objects(self): self.base_object = Object.New('Mesh') self.base_object.setName(self.name) self.add_blender_mesh() self.base_object.link(self.base_mesh) # object will be displayed with wires too self.base_object.setDrawMode(Object.DrawModes.WIRE) self.scene = Scene.GetCurrent() self.scene.link(self.base_object) # add geometry to mesh self.add_blender_data() def load_file(file): global v_data try: tempFile = open(file, 'r') except: exit # read all lines to buffer fileLines = tempFile.readlines() tempFile.close() del tempFile lIdx = 0 # parse all buffered lines while lIdx < len(fileLines): l= fileLines[lIdx].split() if len(l) == 0: continue elif l[0] == 'View': name = "" end_name = 0 start_name = 0 for string in l: if string[0]=="\"" and len(name)==0 and start_name==0: name = name + string[1:] start_name = 1 elif string[-1]=="\"" and len(name)>0 and end_name==0 and start_name==1: name = name + string[:-1] end_name = 1 elif end_name==0 and start_name==1: name = name + string print name elif l[0] == 'ST': tmp1 = l[1] tmp2 = l[19] x1 = float(tmp1[1:]) y1 = float(l[3]) z1 = float(l[5]) x2 = float(l[7]) y2 = float(l[9]) z2 = float(l[11]) x3 = float(l[13]) y3 = float(l[15]) z3 = float(l[17]) val1 = float(tmp2[1:]) val2 = float(l[21]) val3 = float(l[23]) v_data.import_triangle(name, x1, y1, z1, x2, y2, z2, x3, y3, z3, val1, val2, val3) elif l[0] == 'SS': tmp1 = l[1] tmp2 = l[25] x1 = float(tmp1[1:]) y1 = float(l[3]) z1 = float(l[5]) x2 = float(l[7]) y2 = float(l[9]) z2 = float(l[11]) x3 = float(l[13]) y3 = float(l[15]) z3 = float(l[17]) x4 = float(l[19]) y4 = float(l[21]) z4 = float(l[23]) val1 = float(tmp2[1:]) val2 = float(l[27]) val3 = float(l[29]) val4 = float(l[31]) v_data.import_simplex(name, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, val1, val2, val3, val4) elif l[0] == 'VP': tmp1 = l[1] tmp2 = l[7] x = float(tmp1[1:]) y = float(l[3]) z = float(l[5]) dx = float(tmp2[1:]) dy = float(l[9]) dz = float(l[11]) v_data.import_vector(name, x, y, z, dx, dy, dz) lIdx+=1 # ========== create BlENDER DATA ========== v_data.add_blender_objects() # ============ set up GUI DATA ============ # name of file (remove relative/absolute path) l = len(file) i = l while i>0: i -= 1 if file[i] == '/': file_name = file[-l+i+1:] break # file name of loaded data v_data.gui.file_name = file_name if len(v_data.points.values()) > 0: # value_ids are stored in points value_ids = v_data.points.values()[0].val_ids.keys() for value_id in value_ids: #v_data.base_mesh.activeColorLayer = value_id min_val = v_data.points.values()[0].val_ids[value_id].min max_val = v_data.points.values()[0].val_ids[value_id].max s_data = scalar_data(value_id, value_id, min_val, max_val, 0) v_data.gui.scalar_data_list.append(s_data) # first scalar data in list will be selected and used for vizualization if len(v_data.gui.scalar_data_list) > 0: v_data.gui.scalar_data_list[0].selected = 1 v_data.gui.min_scalar_value = str(v_data.gui.scalar_data_list[0].min) v_data.gui.max_scalar_value = str(v_data.gui.scalar_data_list[0].max) v_data.base_mesh.activeColorLayer = v_data.gui.scalar_data_list[0].layer v_data.base_mesh.update() v_data.base_object.sel = True # vector ids are stored in points too vect_ids = v_data.points.values()[0].vect_ids.keys() i = 0 for vect_id in vect_ids: # add object for adding edges(vectors) object = v_data.objects[i] vect_data = vector_data(vect_id, object, 0) v_data.gui.vector_data_list.append(vect_data) i += 1 # first vector data will be selected if len(v_data.gui.vector_data_list) > 0: v_data.gui.vector_data_list[0].selected = 1 #v_data.gui.min_vector_value = str(v_data.gui.vector_data_list[0].min) #v_data.gui.max_vector_value = str(v_data.gui.vector_data_list[0].max) Window.RedrawAll() def generate_animation(): global v_data vect_id = None for vect_data in v_data.gui.vector_data_list: if vect_data.selected == 1: vect_id = vect_data.name if vect_id == None: return max_val = v_data.points.values()[0].vect_ids[vect_id].max min_val = v_data.points.values()[0].vect_ids[vect_id].min fact = max_val - min_val end_time = 50 start_time = -50 life = 25.0 N = 1000 v_data.base_mesh.addVertGroup("particles") particles = Effect.Get(v_data.base_object.getName()) if len(particles)==0: particle = Effect.New(v_data.base_object.getName()) else: particle = particles[0] particle.setTotpart(N) particle.setStartTime(start_time) particle.setEndTime(end_time) particle.flag = Effect.Flags.VERTS particle.setNormfac(1.0) particle.setLife((life, 0, 0, 0)) particle.setStype(1) # particles will be vectors particle.speedVGroup = "particles" particle.vGroup = "particles" v_data.base_mesh.update() replace = Mesh.AssignModes.REPLACE for point in v_data.points.values(): try: vector = point.vectors[vect_id] except: continue co = vector.vec point.vert.no = co weight = vector.length/fact v_data.base_mesh.assignVertsToGroup("particles", [point.id], weight, replace) def run_animation(): pass def destroy_animation(): pass # keyboard and mouse events def event(evt, val): if evt == Draw.ESCKEY: Draw.Exit() return # button events def button_event(evt): global v_data print evt if evt == 1: Draw.Exit() return elif evt == 2: Window.FileSelector(load_file, 'Import POS file', '*.pos') elif evt == 3: generate_animation() elif evt == 4: run_animation() elif evt == 5: destroy_animation() else: if evt<10000 and evt>=100: # scalar data has event smaller then 10000 for data in v_data.gui.scalar_data_list: if data.id == evt: if data.selected == 0: v_data.base_mesh.activeColorLayer = data.layer v_data.gui.min_scalar_value = str(data.min) v_data.gui.max_scalar_value = str(data.max) v_data.base_mesh.update() data.selected = 1 else: if data.selected == 1: data.selected = 0 elif evt>=10000: # vector data has event greater then 10000 for data in v_data.gui.vector_data_list: if data.id == evt: data.selected = 1 - data.selected if data.selected == 1: data.object.layers = [1] else: data.object.layers = [] Draw.Redraw(1) return # GUI of script def gui(): global v_data button_w = 200 button_h = 20 text_h = 10 margin = 15 spectrum_image_h = 80 spectrum_image_w = 40 x = 10 # initial x position y = margin # intiial y position BGL.glClearColor(0.5, 0.5, 0.5, 1) BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) BGL.glColor3f(1.0, 1.0, 1.0) size = Window.GetAreaSize() w = size[0] h = size[1] y = y + text_h string = "Data: " + v_data.gui.file_name BGL.glRasterPos2i(x, h - y) Draw.Text(string, 'normal') y = y + margin + button_h Draw.PushButton("Nacist data", 2, x, h - y, button_w, button_h, "Nacist data") if len(v_data.gui.scalar_data_list)>0: y = y + margin + text_h BGL.glRasterPos2i(10, h - y) Draw.Text("Skalarni data:", 'normal') # list of vectors y = y + margin + button_h Draw.BeginAlign() for data in v_data.gui.scalar_data_list: Draw.Toggle(data.name, data.id, x, h - y, button_w, button_h, data.selected, data.name) y = y + button_h Draw.EndAlign() y = y - button_h # minimal scalar value y = y + margin + text_h BGL.glRasterPos2i(x + spectrum_image_w + 5, h - y) Draw.Text("min: "+v_data.gui.min_scalar_value, 'normal') # maximal scalar value y = y + spectrum_image_h - text_h BGL.glRasterPos2i(x + spectrum_image_w + 5, h - y) Draw.Text("max: "+v_data.gui.max_scalar_value, 'normal') # SPECTRUM img = Image.Load('//Spectrum.png') Draw.Image(img, x, h - y) if len(v_data.gui.vector_data_list)>0: y = y + margin + text_h BGL.glRasterPos2i(x, h - y) Draw.Text("Vektorova data", 'normal') # list of vectors y = y + margin + button_h Draw.BeginAlign() for data in v_data.gui.vector_data_list: Draw.Toggle(data.name, data.id, x, h - y, button_w, button_h, data.selected, data.name) y = y + button_h Draw.EndAlign() y = y - button_h # animation y = y + margin + text_h BGL.glRasterPos2i(x, h - y) Draw.Text("Animace", 'normal') y = y + margin + button_h Draw.BeginAlign() Draw.PushButton("Spocitat animaci", 3, x, h - y, button_w, button_h, "Spocitat animace") y = y + button_h Draw.PushButton("Spustit animaci", 4, x, h - y, button_w, button_h, "Spustit animaci") y = y + button_h Draw.PushButton("Zrusit animaci", 5, x, h - y, button_w, button_h, "Spustit animaci") Draw.EndAlign() y = y + margin + button_h Draw.PushButton("Ukoncit aplikaci", 1, x, h - y, button_w, button_h, "Ukoncit aplikaci") return # only one global variable v_data = vis_data("vis_data") # register callback functions for gui Draw.Register(gui, event, button_event)