#!BPY """ Name: 'COS426 .ray' Blender: 237 Group: 'Export' Tooltip: 'COS426 Raytracer File Format' """ __author__ = "Forrester Cole" __url__ = ["blender"] __version__ = "0.1" __bpydoc__ = """\ This script exports to the COS426 .ray format Usage: File->Export->COS426 .ray """ # -------------------------------------------------------------------------- # ***** 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 ***** # -------------------------------------------------------------------------- import Blender import math import sys def clampEpsilon(x): if abs(x) < 0.00001: return 0 else: return x #blender matrices appear to be [column][row] def transformPoint(mat, point): x = mat[0][0]*point[0] + mat[1][0]*point[1] + mat[2][0]*point[2] + mat[3][0] y = mat[0][1]*point[0] + mat[1][1]*point[1] + mat[2][1]*point[2] + mat[3][1] z = mat[0][2]*point[0] + mat[1][2]*point[1] + mat[2][2]*point[2] + mat[3][2] return x,y,z def transformVector(mat, vec): x = mat[0][0]*vec[0] + mat[1][0]*vec[1] + mat[2][0]*vec[2] y = mat[0][1]*vec[0] + mat[1][1]*vec[1] + mat[2][1]*vec[2] z = mat[0][2]*vec[0] + mat[1][2]*vec[1] + mat[2][2]*vec[2] return x,y,z def formatTriple( input ): return " %f %f %f\n" % (input[0], input[1], input[2]) def formatPair( input ): return " %f %f\n" % (input[0], input[1]) def formatScalar( input ): return " %f\n" % (input) def printMatrix( input ): for i in range(0,4): for j in range(0,4): print str(i) + ' ' + str(j) + ' ' + str(input[i][j]) + ' ' print '\n' # Blender object parsing functions def parseCamera(camera): out = {'type': 'camera'} #print 'camera matrix:' #printMatrix(camera.getMatrix()) out['position'] = transformPoint(camera.getMatrix(), (0,0,0)) out['direction'] = transformVector(camera.getMatrix(), (0,0,-1)) out['up'] = transformVector(camera.getMatrix(), (0,1,0)) #print 'up vector' + str(out['up']) # Blender has a weird camera lens # (copied from the VRML exporter) context = Blender.Scene.getCurrent().getRenderingContext() ratio = float(context.imageSizeY())/float(context.imageSizeX()) lens = (360* (math.atan(ratio *16 / camera.data.getLens()) / math.pi))*(math.pi/180)*0.5 out['halfangle'] = min(lens, math.pi / 2) return out def parseLightPoint(light): out = {'type': 'point_light'} lamp_data = Blender.Lamp.Get(light.data.getName()) out['color'] = lamp_data.col out['position'] = transformPoint(light.getMatrix(), (0,0,0)) out['energy'] = lamp_data.energy out['attenuation'] = (1,0,0) return out def parseLightDirectional(light): out = {'type': 'directional_light'} lamp_data = Blender.Lamp.Get(light.data.getName()) out['color'] = lamp_data.col out['direction'] = transformVector(light.getMatrix(), (0,0,-1)) out['energy'] = lamp_data.energy return out def parseLightSpot(light): out = {'type': 'spot_light'} lamp_data = Blender.Lamp.Get(light.data.getName()) out['color'] = lamp_data.col out['position'] = transformPoint(light.getMatrix(), (0,0,0)) out['direction'] = transformVector(light.getMatrix(), (0,0,-1)) out['energy'] = lamp_data.energy out['attenuation'] = (1,0,0) out['cone'] = lamp_data.getSpotSize(), lamp_data.getSpotBlend() return out def parseMaterial(material): out = {'type': 'material'} out['ambient'] = (material.rgbCol[0]*material.amb, material.rgbCol[1]*material.amb, material.rgbCol[2]*material.amb) out['diffuse'] = material.rgbCol out['specular'] = material.specCol out['emissive'] = (material.rgbCol[0]*material.emit, material.rgbCol[1]*material.emit, material.rgbCol[2]*material.emit) out['shininess'] = material.hard/512.0 out['transparency'] = material.translucency out['refraction'] = 1 textures = material.getTextures( ) for mtex in textures: if not ( mtex == None ): texture = mtex.tex if ( texture.type == Blender.Texture.Types.IMAGE ): out['texture'] = texture.getImage().getName() return out def parseMesh(mesh_object): out = {'type': 'mesh', 'tris': [], 'verts': [], 'materials': []} mesh = mesh_object.getData() transform = mesh_object.getMatrix() vert_dict = {} # just to keep track of which vertices we have seen for (face_num, face) in enumerate(mesh.faces): tri_indices = [] for (vert_num, vert) in enumerate(face.v): vert_data = {'position': transformPoint(transform, tuple(vert.co))} # BROKEN - must transform normal by inverse transpose if face.smooth: vert_data['normal'] = transformVector(transform, tuple(vert.no)) else: vert_data['normal'] = transformVector(transform, tuple(face.no)) # drop epsilon values to allow proper hashing vert_data['normal'] = tuple(map(clampEpsilon, vert_data['normal'])) key = vert.index, vert_data['normal'] if mesh.hasFaceUV(): vert_data['texcoord'] = face.uv[vert_num] key = key + ( tuple(map(clampEpsilon, face.uv[vert_num])) ) if not vert_dict.has_key(key): vert_dict[key] = len(out['verts']) out['verts'].append(vert_data) tri_indices.append(vert_dict[key]) out['tris'].append( tuple(tri_indices) ) for mat_name in mesh.materials: out['materials'].append( parseMaterial( Blender.Material.Get(mat_name.name) ) ) return out def parseBackground(world): color = world.getHor() return tuple(color) def parseAmbient(world): color = world.getAmb() return tuple(color) # .ray format writing functions def writeCamera(file, data): file.write("#camera\n"); file.write(formatTriple(data['position'])) file.write(formatTriple(data['direction'])) file.write(formatTriple(data['up'])) file.write(formatScalar(data['halfangle'])) file.write('\n\n') def writeLightPoint(file, data): file.write("#light_point\n"); file.write(formatTriple(data['color'])) file.write(formatTriple(data['position'])) file.write(formatTriple(data['attenuation'])) def writeLightDirectional(file, data): file.write("#light_dir\n"); file.write(formatTriple(data['color'])) file.write(formatTriple(data['direction'])) def writeLightSpot(file, data): file.write("#light_spot\n"); file.write(formatTriple(data['color'])) file.write(formatTriple(data['position'])) file.write(formatTriple(data['direction'])) file.write(formatTriple(data['attenuation'])) file.write(formatPair(data['cone'])) def writeLights(file, data): file.write("#light_num %d\n" % (len(data))) for light in data: if light['type'] == 'point_light': writeLightPoint(file, light) elif light['type'] == 'spot_light': writeLightSpot(file, light) elif light['type'] == 'directional_light': writeLightDirectional(file, light) file.write('\n\n') def writeMaterials(file, data): textures = [] for material in data: if material.has_key('texture') and not material['texture'] in textures: textures.append(material['texture']) if len(textures) > 0: file.write("#texture_num %d\n" % len(textures)) for tex in textures: file.write("#texture %s\n" % tex) file.write('\n\n') file.write("#material_num %d\n" % (len(data))) for material in data: file.write("#material\n") for key in ('ambient', 'diffuse', 'specular', 'emissive'): file.write(formatTriple(material[key])) file.write(formatTriple( (material['shininess'], material['transparency'], material['refraction']) )) if material.has_key('texture'): file.write(' %d\n' % textures.index(material['texture'])) else: file.write(' -1\n') file.write(' !!\n') file.write('\n\n') def writeVertices(file, data): file.write('#vertex_num %d\n' % (len(data))) for vertex in data: file.write("#vertex\n") file.write(formatTriple(vertex['position'])) file.write(formatTriple(vertex['normal'])) if vertex.has_key('texcoord'): file.write(formatPair(vertex['texcoord'])) else: file.write(formatPair((0,0))) file.write('\n') file.write('\n\n') def writeShapeTriangles(file, data): for group in data: file.write('#group_begin\n') file.write('1 0 0 0\n0 1 0 0\n0 0 1 0\n0 0 0 1\n') for shape in group: file.write('#shape_triangle %d\n' % shape[0]) file.write(' %d %d %d\n' % shape[1:]) file.write('\n') file.write('#group_end\n') file.write('\n\n') def writeBackground(file, data): file.write('#background %f %f %f\n\n' % data) def writeAmbient(file, data): file.write('#ambient %f %f %f\n\n' % data) # main function def write(filename): out = file(filename, "w") data_dict = { 'lights': [], 'materials': [], 'verts': [], 'tri_groups': [] } # global world information world = Blender.World.Get() if len(world) > 0: data_dict['background'] = parseBackground(world[0]) data_dict['ambient'] = parseAmbient(world[0]) material_num = 0 vert_offset = 0 for node in Blender.Object.Get(): node_type = node.getType() node_name = node.getName() #print 'Parsing ' + node_name if node_type == "Camera": data_dict['camera'] = parseCamera(node) elif node_type == "Mesh": parsed_mesh = parseMesh( node ) if len(parsed_mesh['materials']) > 0: material_num = len(data_dict['materials']) data_dict['materials'].extend(parsed_mesh['materials']) vert_offset = len(data_dict['verts']) data_dict['verts'].extend(parsed_mesh['verts']) group = [] for tri in parsed_mesh['tris']: group.append( (material_num, tri[0] + vert_offset, tri[1] + vert_offset, tri[2] + vert_offset ) ) data_dict['tri_groups'].append(group) elif node_type == "Lamp": lamp_data=Blender.Lamp.Get(node.data.getName()) if lamp_data.getType() == Blender.Lamp.Types.Lamp: data_dict['lights'].append( parseLightPoint(node) ) elif lamp_data.getType() == Blender.Lamp.Types.Spot: data_dict['lights'].append( parseLightSpot(node) ) elif lamp_data.getType() == Blender.Lamp.Types.Sun: data_dict['lights'].append( parseLightDirectional(node) ) # print 'read total %d materials and %d vertices\n' % (len(data_dict['materials']), len(data_dict['verts'])) if data_dict.has_key('background'): writeBackground(out, data_dict['background']) if data_dict.has_key('ambient'): writeAmbient(out, data_dict['ambient']) writeCamera(out, data_dict['camera']) writeLights(out, data_dict['lights']) writeMaterials(out, data_dict['materials']) writeVertices(out, data_dict['verts']) writeShapeTriangles(out, data_dict['tri_groups']) out.close() Blender.Window.FileSelector(write, "Export") """ elif lmpType == Lamp.Types.Spot: self.writeSpotLight(thisObj, lmpName) elif lmpType == Lamp.Types.Sun: self.writeDirectionalLight(thisObj, lmpName) """