BPython:
-- fixing a last minute bug: scripts w/o guis that called the file selector were not being checked for errors, which could cause crash dumps upon exiting. -- docs: updates for Draw (fixed example) and Material (added tex related methods docs) Scripts: -- added some more scripts, all I could get in shape in time (at least they export / import back). Only tested on linux.
This commit is contained in:
19
release/scripts/mod_flags.py
Normal file
19
release/scripts/mod_flags.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2002 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve.com |
|
||||||
|
# | October 25, 2002 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Share Global Variables Across Modules |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
|
||||||
|
blender_version = Blender.Get('version')
|
||||||
|
blender_version_str = `blender_version`[0] + '.' + `blender_version`[1:]
|
||||||
|
|
||||||
|
show_progress = 1 # Set to 0 for faster performance
|
||||||
|
average_vcols = 1 # Off for per-face, On for per-vertex
|
||||||
|
overwrite_mesh_name = 0 # Set to 0 for safety
|
||||||
178
release/scripts/mod_meshtools.py
Normal file
178
release/scripts/mod_meshtools.py
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2001 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve. |
|
||||||
|
# | September 28, 2002 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Common Functions For All Modules |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
import sys#, random, operator
|
||||||
|
import mod_flags
|
||||||
|
|
||||||
|
try:
|
||||||
|
import random, operator
|
||||||
|
# ===================================
|
||||||
|
# ==== Append Faces To Face List ====
|
||||||
|
# ===================================
|
||||||
|
def append_faces(mesh, faces, facesuv, uvcoords):
|
||||||
|
r = random.randrange(200, 255, 50)
|
||||||
|
g = random.randrange(100, 200, 50)
|
||||||
|
b = random.randrange(0, 100, 50)
|
||||||
|
for i in range(len(faces)):
|
||||||
|
if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Generating Faces")
|
||||||
|
numfaceverts=len(faces[i])
|
||||||
|
if numfaceverts <= 4: # This face is a triangle or quad
|
||||||
|
face = Blender.NMesh.Face()
|
||||||
|
for j in range(numfaceverts):
|
||||||
|
index = faces[i][j]
|
||||||
|
face.v.append(mesh.verts[index])
|
||||||
|
if len(uvcoords) > 1:
|
||||||
|
uvidx = facesuv[i][j]
|
||||||
|
face.uv.append(uvcoords[uvidx])
|
||||||
|
face.mode = 0
|
||||||
|
#face.col = [Blender.NMesh.Col(r, g, b)]*4 # Random color
|
||||||
|
face.col = [Blender.NMesh.Col()]*4
|
||||||
|
mesh.faces.append(face)
|
||||||
|
else: # Triangulate n-sided convex polygon.
|
||||||
|
a, b, c = 0, 1, 2 # Indices of first triangle.
|
||||||
|
for j in range(numfaceverts-2): # Number of triangles in polygon.
|
||||||
|
face = Blender.NMesh.Face()
|
||||||
|
face.v.append(mesh.verts[faces[i][a]])
|
||||||
|
face.v.append(mesh.verts[faces[i][b]])
|
||||||
|
face.v.append(mesh.verts[faces[i][c]])
|
||||||
|
b = c; c += 1
|
||||||
|
mesh.faces.append(face)
|
||||||
|
#face.smooth = 1
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# ==== Append Verts to Vertex List ====
|
||||||
|
# =====================================
|
||||||
|
def append_verts(mesh, verts, normals):
|
||||||
|
#print "Number of normals:", len(normals)
|
||||||
|
#print "Number of verts :", len(verts)
|
||||||
|
for i in range(len(verts)):
|
||||||
|
if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(verts), "Generating Verts")
|
||||||
|
x, y, z = verts[i]
|
||||||
|
mesh.verts.append(Blender.NMesh.Vert(x, y, z))
|
||||||
|
if normals:
|
||||||
|
mesh.verts[i].no[0] = normals[i][0]
|
||||||
|
mesh.verts[i].no[1] = normals[i][1]
|
||||||
|
mesh.verts[i].no[2] = normals[i][2]
|
||||||
|
|
||||||
|
# =============================
|
||||||
|
# ==== Create Blender Mesh ====
|
||||||
|
# =============================
|
||||||
|
def create_mesh(verts, faces, objname, facesuv=[], uvcoords=[], normals=[]):
|
||||||
|
if normals: normal_flag = 0
|
||||||
|
else: normal_flag = 1
|
||||||
|
mesh = Blender.NMesh.GetRaw()
|
||||||
|
append_verts(mesh, verts, normals)
|
||||||
|
append_faces(mesh, faces, facesuv, uvcoords)
|
||||||
|
if not mod_flags.overwrite_mesh_name:
|
||||||
|
objname = versioned_name(objname)
|
||||||
|
Blender.NMesh.PutRaw(mesh, objname, normal_flag) # Name the Mesh
|
||||||
|
Blender.Object.GetSelected()[0].name=objname # Name the Object
|
||||||
|
Blender.Redraw()
|
||||||
|
|
||||||
|
except ImportError: pass
|
||||||
|
|
||||||
|
# ================================
|
||||||
|
# ==== Increment Name Version ====
|
||||||
|
# ================================
|
||||||
|
def versioned_name(objname):
|
||||||
|
existing_names = []
|
||||||
|
for object in Blender.Object.Get():
|
||||||
|
existing_names.append(object.name)
|
||||||
|
existing_names.append(object.data.name)
|
||||||
|
if objname in existing_names: # don't over-write other names
|
||||||
|
try:
|
||||||
|
name, ext = objname.split('.')
|
||||||
|
except ValueError:
|
||||||
|
name, ext = objname, ''
|
||||||
|
try:
|
||||||
|
num = int(ext)
|
||||||
|
root = name
|
||||||
|
except ValueError:
|
||||||
|
root = objname
|
||||||
|
for i in xrange(1, 1000):
|
||||||
|
objname = "%s.%03d" % (root, i)
|
||||||
|
if objname not in existing_names:
|
||||||
|
break
|
||||||
|
return objname
|
||||||
|
|
||||||
|
# =============================
|
||||||
|
# ==== Print Text In A Box ====
|
||||||
|
# =============================
|
||||||
|
def print_boxed(text):
|
||||||
|
lines = text.splitlines()
|
||||||
|
maxlinelen = max(map(len, lines))
|
||||||
|
print '+-' + '-'*maxlinelen + '-+'
|
||||||
|
for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
|
||||||
|
print '+-' + '-'*maxlinelen + '-+'
|
||||||
|
|
||||||
|
print '\a\r', # beep when done
|
||||||
|
|
||||||
|
# =================================================
|
||||||
|
# ==== Get Euler Angles From A Rotation Matrix ====
|
||||||
|
# =================================================
|
||||||
|
#def mat2euler(mat):
|
||||||
|
# angle_y = -math.asin(mat[0][2])
|
||||||
|
# c = math.cos(angle_y)
|
||||||
|
# if math.fabs(c) > 0.005:
|
||||||
|
# angle_x = math.atan2(mat[1][2]/c, mat[2][2]/c)
|
||||||
|
# angle_z = math.atan2(mat[0][1]/c, mat[0][0]/c)
|
||||||
|
# else:
|
||||||
|
# angle_x = 0.0
|
||||||
|
# angle_z = -math.atan2(mat[1][0], mat[1][1])
|
||||||
|
# return (angle_x, angle_y, angle_z)
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
# ==== Transpose A Matrix ====
|
||||||
|
# ============================
|
||||||
|
def transpose(A):
|
||||||
|
S = len(A)
|
||||||
|
T = len(A[0])
|
||||||
|
B = [[None]*S for i in range(T)]
|
||||||
|
for i in range(T):
|
||||||
|
for j in range(S):
|
||||||
|
B[i][j] = A[j][i]
|
||||||
|
return B
|
||||||
|
|
||||||
|
#def append_ntimes(Seq, N):
|
||||||
|
# Seq = reduce(operator.add, Seq) # Flatten once
|
||||||
|
# if N == 1: return Seq
|
||||||
|
# return append_ntimes(Seq, N-1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# print "mesh.has_col ", mesh.has_col
|
||||||
|
# print "mesh.hasVertexColours()", mesh.hasVertexColours()
|
||||||
|
# print "mesh.hasFaceUV() ", mesh.hasFaceUV()
|
||||||
|
# print "mesh.has_uvco ", mesh.has_uvco
|
||||||
|
|
||||||
|
# # =============================
|
||||||
|
# # ==== Create Blender Mesh ====
|
||||||
|
# # =============================
|
||||||
|
# def create_mesh_old(verts, faces, objname):
|
||||||
|
# mesh = Blender.NMesh.GetRaw()
|
||||||
|
# # === Vertex List ===
|
||||||
|
# for i in range(len(verts)):
|
||||||
|
# x, y, z = verts[i]
|
||||||
|
# mesh.verts.append(Blender.NMesh.Vert(x, y ,z))
|
||||||
|
# # === Face List ===
|
||||||
|
# for i in range(len(faces)):
|
||||||
|
# face = Blender.NMesh.Face()
|
||||||
|
# for j in range(len(faces[i])):
|
||||||
|
# index = faces[i][j]
|
||||||
|
# face.v.append(mesh.verts[index])
|
||||||
|
# mesh.faces.append(face)
|
||||||
|
# # === Name the Object ===
|
||||||
|
# Blender.NMesh.PutRaw(mesh, objname)
|
||||||
|
# object = Blender.Object.GetSelected()
|
||||||
|
# object[0].name=objname
|
||||||
|
# Blender.Redraw()
|
||||||
|
|
||||||
72
release/scripts/off_export.py
Normal file
72
release/scripts/off_export.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#!BPY
|
||||||
|
|
||||||
|
"""
|
||||||
|
Name: 'OFF...'
|
||||||
|
Blender: 232
|
||||||
|
Group: 'Export'
|
||||||
|
Tooltip: 'Export selected mesh to Object File Format (*.off)'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2002 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve.com |
|
||||||
|
# | February 3, 2001 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Read and write Object File Format (*.off) |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
#import time
|
||||||
|
import mod_flags, mod_meshtools
|
||||||
|
|
||||||
|
# ==============================
|
||||||
|
# ====== Write OFF Format ======
|
||||||
|
# ==============================
|
||||||
|
def write(filename):
|
||||||
|
#start = time.clock()
|
||||||
|
file = open(filename, "wb")
|
||||||
|
|
||||||
|
objects = Blender.Object.GetSelected()
|
||||||
|
objname = objects[0].name
|
||||||
|
meshname = objects[0].data.name
|
||||||
|
mesh = Blender.NMesh.GetRaw(meshname)
|
||||||
|
#mesh = Blender.NMesh.GetRawFromObject(meshname) # for SubSurf
|
||||||
|
obj = Blender.Object.Get(objname)
|
||||||
|
|
||||||
|
# === OFF Header ===
|
||||||
|
file.write("OFF\n")
|
||||||
|
file.write("%d %d %d\n" % (len(mesh.verts), len(mesh.faces), 0))
|
||||||
|
|
||||||
|
# === Vertex List ===
|
||||||
|
for i in range(len(mesh.verts)):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts")
|
||||||
|
x, y, z = mesh.verts[i].co
|
||||||
|
file.write("%f %f %f\n" % (x, y, z))
|
||||||
|
|
||||||
|
# === Face List ===
|
||||||
|
for i in range(len(mesh.faces)):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces")
|
||||||
|
file.write(`len(mesh.faces[i].v)`+' ')
|
||||||
|
mesh.faces[i].v.reverse()
|
||||||
|
for j in range(len(mesh.faces[i].v)):
|
||||||
|
file.write(`mesh.faces[i].v[j].index`+' ')
|
||||||
|
file.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
|
||||||
|
file.close()
|
||||||
|
#end = time.clock()
|
||||||
|
#seconds = " in %.2f %s" % (end-start, "seconds")
|
||||||
|
message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
|
||||||
|
def fs_callback(filename):
|
||||||
|
if filename.find('.off', -4) <= 0: filename += '.off'
|
||||||
|
write(filename)
|
||||||
|
|
||||||
|
Blender.Window.FileSelector(fs_callback, "OFF Export")
|
||||||
75
release/scripts/off_import.py
Normal file
75
release/scripts/off_import.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#!BPY
|
||||||
|
|
||||||
|
"""
|
||||||
|
Name: 'OFF...'
|
||||||
|
Blender: 232
|
||||||
|
Group: 'Import'
|
||||||
|
Tooltip: 'Import Object File Format (*.off)'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2002 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve.com |
|
||||||
|
# | February 3, 2001 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Read and write Object File Format (*.off) |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
#import time
|
||||||
|
import mod_flags, mod_meshtools
|
||||||
|
|
||||||
|
# =============================
|
||||||
|
# ====== Read OFF Format ======
|
||||||
|
# =============================
|
||||||
|
def read(filename):
|
||||||
|
#start = time.clock()
|
||||||
|
file = open(filename, "rb")
|
||||||
|
|
||||||
|
verts = []
|
||||||
|
faces = []
|
||||||
|
|
||||||
|
# === OFF Header ===
|
||||||
|
offheader = file.readline()
|
||||||
|
numverts, numfaces, null = file.readline().split()
|
||||||
|
numverts = int(numverts)
|
||||||
|
numfaces = int(numfaces)
|
||||||
|
|
||||||
|
# === Vertex List ===
|
||||||
|
for i in range(numverts):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
|
||||||
|
x, y, z = file.readline().split()
|
||||||
|
x, y, z = float(x), float(y), float(z)
|
||||||
|
verts.append((x, y, z))
|
||||||
|
|
||||||
|
# === Face List ===
|
||||||
|
for i in range(numfaces):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces")
|
||||||
|
line = file.readline().split()
|
||||||
|
numfaceverts = len(line)-1
|
||||||
|
facev = []
|
||||||
|
for j in range(numfaceverts):
|
||||||
|
index = int(line[j+1])
|
||||||
|
facev.append(index)
|
||||||
|
facev.reverse()
|
||||||
|
faces.append(facev)
|
||||||
|
|
||||||
|
objname = Blender.sys.splitext(Blender.sys.basename(filename))[0]
|
||||||
|
|
||||||
|
mod_meshtools.create_mesh(verts, faces, objname)
|
||||||
|
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
|
||||||
|
file.close()
|
||||||
|
#end = time.clock()
|
||||||
|
#seconds = " in %.2f %s" % (end-start, "seconds")
|
||||||
|
message = "Successfully imported " + Blender.sys.basename(filename)# + seconds
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
|
||||||
|
def fs_callback(filename):
|
||||||
|
read(filename)
|
||||||
|
|
||||||
|
Blender.Window.FileSelector(fs_callback, "OFF Import")
|
||||||
89
release/scripts/radiosity_export.py
Normal file
89
release/scripts/radiosity_export.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#!BPY
|
||||||
|
|
||||||
|
"""
|
||||||
|
Name: 'Radiosity...'
|
||||||
|
Blender: 232
|
||||||
|
Group: 'Export'
|
||||||
|
Tooltip: 'Export selected mesh (with vertex colors) to Radiosity File Format (*.radio)'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2002 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve.com |
|
||||||
|
# | April 11, 2002 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Read and write Radiosity File Format (*.radio) |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
#import time
|
||||||
|
import mod_flags, mod_meshtools
|
||||||
|
try:
|
||||||
|
import struct
|
||||||
|
except:
|
||||||
|
msg = "Error: you need a full Python install to run this script."
|
||||||
|
mod_meshtools.print_boxed(msg)
|
||||||
|
|
||||||
|
# ================================
|
||||||
|
# ====== Write Radio Format ======
|
||||||
|
# ================================
|
||||||
|
def write(filename):
|
||||||
|
#start = time.clock()
|
||||||
|
file = open(filename, "wb")
|
||||||
|
|
||||||
|
objects = Blender.Object.GetSelected()
|
||||||
|
objname = objects[0].name
|
||||||
|
meshname = objects[0].data.name
|
||||||
|
mesh = Blender.NMesh.GetRaw(meshname)
|
||||||
|
obj = Blender.Object.Get(objname)
|
||||||
|
|
||||||
|
if not mesh.hasVertexColours():
|
||||||
|
message = "Please assign vertex colors before exporting.\n"
|
||||||
|
message += objname + " object was not saved."
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
return
|
||||||
|
|
||||||
|
# === Object Name ===
|
||||||
|
file.write(struct.pack("<h", len(objname)))
|
||||||
|
file.write(struct.pack("<"+`len(objname)`+"s", objname))
|
||||||
|
|
||||||
|
# === Vertex List ===
|
||||||
|
file.write(struct.pack("<l", len(mesh.verts)))
|
||||||
|
for i in range(len(mesh.verts)):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts")
|
||||||
|
|
||||||
|
x, y, z = mesh.verts[i].co
|
||||||
|
file.write(struct.pack("<fff", x, y, z))
|
||||||
|
|
||||||
|
# === Face List ===
|
||||||
|
file.write(struct.pack("<l", len(mesh.faces)))
|
||||||
|
for i in range(len(mesh.faces)):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces")
|
||||||
|
|
||||||
|
file.write(struct.pack("<b", len(mesh.faces[i].v)))
|
||||||
|
for j in range(len(mesh.faces[i].v)):
|
||||||
|
file.write(struct.pack("<h", mesh.faces[i].v[j].index))
|
||||||
|
|
||||||
|
for j in range(4): # .col always has a length of 4
|
||||||
|
file.write(struct.pack("<BBBB", mesh.faces[i].col[j].r,
|
||||||
|
mesh.faces[i].col[j].g,
|
||||||
|
mesh.faces[i].col[j].b,
|
||||||
|
mesh.faces[i].col[j].a))
|
||||||
|
|
||||||
|
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
|
||||||
|
file.close()
|
||||||
|
#end = time.clock()
|
||||||
|
#seconds = " in %.2f %s" % (end-start, "seconds")
|
||||||
|
message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
|
||||||
|
def fs_callback(filename):
|
||||||
|
if filename.find('.radio', -6) <= 0: filename += '.radio'
|
||||||
|
write(filename)
|
||||||
|
|
||||||
|
Blender.Window.FileSelector(fs_callback, "Radio Export")
|
||||||
93
release/scripts/radiosity_import.py
Normal file
93
release/scripts/radiosity_import.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#!BPY
|
||||||
|
|
||||||
|
"""
|
||||||
|
Name: 'Radiosity...'
|
||||||
|
Blender: 232
|
||||||
|
Group: 'Import'
|
||||||
|
Tooltip: 'Import Radiosity File Format (*.radio) with vertex colors'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2002 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve.com |
|
||||||
|
# | April 11, 2002 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Read and write Radiosity File Format (*.radio) |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
#import time
|
||||||
|
import mod_flags, mod_meshtools
|
||||||
|
try:
|
||||||
|
import struct
|
||||||
|
except:
|
||||||
|
msg = "Error: you need a full Python install to run this script."
|
||||||
|
mod_meshtools.print_boxed(msg)
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# ====== Read Radio Format ======
|
||||||
|
# ===============================
|
||||||
|
def read(filename):
|
||||||
|
#start = time.clock()
|
||||||
|
file = open(filename, "rb")
|
||||||
|
mesh = Blender.NMesh.GetRaw()
|
||||||
|
mesh.addMaterial(Blender.Material.New())
|
||||||
|
|
||||||
|
# === Object Name ===
|
||||||
|
namelen, = struct.unpack("<h", file.read(2))
|
||||||
|
objname, = struct.unpack("<"+`namelen`+"s", file.read(namelen))
|
||||||
|
|
||||||
|
# === Vertex List ===
|
||||||
|
numverts, = struct.unpack("<l", file.read(4))
|
||||||
|
for i in range(numverts):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
|
||||||
|
x, y, z = struct.unpack("<fff", file.read(12))
|
||||||
|
mesh.verts.append(Blender.NMesh.Vert(x, y, z))
|
||||||
|
|
||||||
|
# === Face List ===
|
||||||
|
numfaces, = struct.unpack("<l", file.read(4))
|
||||||
|
for i in range(numfaces):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces")
|
||||||
|
|
||||||
|
face = Blender.NMesh.Face()
|
||||||
|
numfaceverts, = struct.unpack("<b", file.read(1))
|
||||||
|
|
||||||
|
for j in range(numfaceverts):
|
||||||
|
index, = struct.unpack("<h", file.read(2))
|
||||||
|
face.v.append(mesh.verts[index])
|
||||||
|
|
||||||
|
for j in range(4):
|
||||||
|
r, g, b, a = struct.unpack("<BBBB", file.read(4))
|
||||||
|
vertexcolor = Blender.NMesh.Col(r, g, b, a)
|
||||||
|
face.col.append(vertexcolor)
|
||||||
|
|
||||||
|
if len(face.v) == 3:
|
||||||
|
face.uv = [ (0,0), (0,1), (1,1) ]
|
||||||
|
else:
|
||||||
|
face.uv = [ (0,0), (0,1), (1,1), (1,0) ]
|
||||||
|
|
||||||
|
face.mode = 0
|
||||||
|
mesh.faces.append(face)
|
||||||
|
|
||||||
|
# ->tools.create_mesh(verts, faces, objname):
|
||||||
|
Blender.NMesh.PutRaw(mesh, objname)
|
||||||
|
object = Blender.Object.GetSelected()
|
||||||
|
object[0].name=objname
|
||||||
|
# ->tools.create_mesh(verts, faces, objname):
|
||||||
|
|
||||||
|
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
|
||||||
|
file.close()
|
||||||
|
#end = time.clock()
|
||||||
|
#seconds = " in %.2f %s" % (end-start, "seconds")
|
||||||
|
message = "Successfully imported " + Blender.sys.basename(filename)# + seconds
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
|
||||||
|
def fs_callback(filename):
|
||||||
|
read(filename)
|
||||||
|
|
||||||
|
Blender.Window.FileSelector(fs_callback, "Radio Import")
|
||||||
66
release/scripts/raw_export.py
Normal file
66
release/scripts/raw_export.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#!BPY
|
||||||
|
|
||||||
|
"""
|
||||||
|
Name: 'Raw Triangle...'
|
||||||
|
Blender: 232
|
||||||
|
Group: 'Export'
|
||||||
|
Tooltip: 'Export selected mesh to Raw Triangle Format (*.raw)'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2002 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve.com |
|
||||||
|
# | April 28, 2002 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Read and write RAW Triangle File Format (*.raw) |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender, sys
|
||||||
|
#import time
|
||||||
|
import mod_flags, mod_meshtools
|
||||||
|
|
||||||
|
# ===================================
|
||||||
|
# ==== Write RAW Triangle Format ====
|
||||||
|
# ===================================
|
||||||
|
def write(filename):
|
||||||
|
#start = time.clock()
|
||||||
|
file = open(filename, "wb")
|
||||||
|
|
||||||
|
objects = Blender.Object.GetSelected()
|
||||||
|
objname = objects[0].name
|
||||||
|
meshname = objects[0].data.name
|
||||||
|
mesh = Blender.NMesh.GetRaw(meshname)
|
||||||
|
obj = Blender.Object.Get(objname)
|
||||||
|
|
||||||
|
|
||||||
|
std=sys.stdout
|
||||||
|
sys.stdout=file
|
||||||
|
for face in mesh.faces:
|
||||||
|
if len(face.v) == 3: # triangle
|
||||||
|
v1, v2, v3 = face.v
|
||||||
|
faceverts = tuple(v1.co) + tuple(v2.co) + tuple(v3.co)
|
||||||
|
print "% f % f % f % f % f % f % f % f % f" % faceverts
|
||||||
|
else: # quadrilateral
|
||||||
|
v1, v2, v3, v4 = face.v
|
||||||
|
faceverts1 = tuple(v1.co) + tuple(v2.co) + tuple(v3.co)
|
||||||
|
faceverts2 = tuple(v3.co) + tuple(v4.co) + tuple(v1.co)
|
||||||
|
print "% f % f % f % f % f % f % f % f % f" % faceverts1
|
||||||
|
print "% f % f % f % f % f % f % f % f % f" % faceverts2
|
||||||
|
sys.stdout=std
|
||||||
|
|
||||||
|
|
||||||
|
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
|
||||||
|
file.close()
|
||||||
|
#end = time.clock()
|
||||||
|
#seconds = " in %.2f %s" % (end-start, "seconds")
|
||||||
|
message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
|
||||||
|
def fs_callback(filename):
|
||||||
|
if filename.find('.raw', -4) <= 0: filename += '.raw'
|
||||||
|
write(filename)
|
||||||
|
|
||||||
|
Blender.Window.FileSelector(fs_callback, "Raw Export")
|
||||||
68
release/scripts/raw_import.py
Normal file
68
release/scripts/raw_import.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#!BPY
|
||||||
|
|
||||||
|
"""
|
||||||
|
Name: 'Raw Triangle...'
|
||||||
|
Blender: 232
|
||||||
|
Group: 'Import'
|
||||||
|
Tooltip: 'Import Raw Triangle File Format (*.raw)'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2002 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve.com |
|
||||||
|
# | April 28, 2002 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Read and write RAW Triangle File Format (*.raw) |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
#import time
|
||||||
|
import mod_flags, mod_meshtools
|
||||||
|
|
||||||
|
# ==================================
|
||||||
|
# ==== Read RAW Triangle Format ====
|
||||||
|
# ==================================
|
||||||
|
def read(filename):
|
||||||
|
#start = time.clock()
|
||||||
|
file = open(filename, "rb")
|
||||||
|
|
||||||
|
# Collect data from RAW format
|
||||||
|
faces = []
|
||||||
|
for line in file.readlines():
|
||||||
|
try:
|
||||||
|
f1, f2, f3, f4, f5, f6, f7, f8, f9 = map(float, line.split())
|
||||||
|
faces.append([(f1, f2, f3), (f4, f5, f6), (f7, f8, f9)])
|
||||||
|
except: # Quad
|
||||||
|
f1, f2, f3, f4, f5, f6, f7, f8, f9, A, B, C = map(float, line.split())
|
||||||
|
faces.append([(f1, f2, f3), (f4, f5, f6), (f7, f8, f9), (A, B, C)])
|
||||||
|
|
||||||
|
# Generate verts and faces lists, without duplicates
|
||||||
|
verts = []
|
||||||
|
coords = {}
|
||||||
|
index = 0
|
||||||
|
for i in range(len(faces)):
|
||||||
|
for j in range(len(faces[i])):
|
||||||
|
vertex = faces[i][j]
|
||||||
|
if not coords.has_key(vertex):
|
||||||
|
coords[vertex] = index
|
||||||
|
index += 1
|
||||||
|
verts.append(vertex)
|
||||||
|
faces[i][j] = coords[vertex]
|
||||||
|
|
||||||
|
objname = Blender.sys.splitext(Blender.sys.basename(filename))[0]
|
||||||
|
|
||||||
|
mod_meshtools.create_mesh(verts, faces, objname)
|
||||||
|
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
|
||||||
|
file.close()
|
||||||
|
#end = time.clock()
|
||||||
|
#seconds = " in %.2f %s" % (end-start, "seconds")
|
||||||
|
message = "Successfully imported " + Blender.sys.basename(filename)# + seconds
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
|
||||||
|
def fs_callback(filename):
|
||||||
|
read(filename)
|
||||||
|
|
||||||
|
Blender.Window.FileSelector(fs_callback, "Raw Import")
|
||||||
232
release/scripts/videoscape_export.py
Normal file
232
release/scripts/videoscape_export.py
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
#!BPY
|
||||||
|
|
||||||
|
"""
|
||||||
|
Name: 'Videoscape (with Vertex Colors)...'
|
||||||
|
Blender: 232
|
||||||
|
Group: 'Export'
|
||||||
|
Tooltip: 'Export selected mesh to VideoScape File Format (*.obj)'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Copyright (c) 2001 Anthony D'Agostino |
|
||||||
|
# | http://ourworld.compuserve.com/homepages/scorpius |
|
||||||
|
# | scorpius@compuserve.com |
|
||||||
|
# | June 5, 2001 |
|
||||||
|
# | Released under the Blender Artistic Licence (BAL) |
|
||||||
|
# | Import Export Suite v0.5 |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
# | Write Videoscape File Format (*.obj NOT WAVEFRONT OBJ) |
|
||||||
|
# | Includes a *fast* algorithm for averaging vertex colors |
|
||||||
|
# | Blender's a|w doesn't export proper vertex colors |
|
||||||
|
# +---------------------------------------------------------+
|
||||||
|
|
||||||
|
import Blender, mod_meshtools
|
||||||
|
#import time
|
||||||
|
import mod_flags
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# ====== Write VideoScape Format ======
|
||||||
|
# =====================================
|
||||||
|
def write(filename):
|
||||||
|
#start = time.clock()
|
||||||
|
file = open(filename, "wb")
|
||||||
|
|
||||||
|
objects = Blender.Object.GetSelected()
|
||||||
|
objname = objects[0].name
|
||||||
|
meshname = objects[0].data.name
|
||||||
|
mesh = Blender.NMesh.GetRaw(meshname)
|
||||||
|
obj = Blender.Object.Get(objname)
|
||||||
|
|
||||||
|
if not mesh.hasVertexColours():
|
||||||
|
message = "Please assign vertex colors before exporting.\n"
|
||||||
|
message += objname + " object was not saved."
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
return
|
||||||
|
|
||||||
|
vcols = average_vertexcolors(mesh)
|
||||||
|
|
||||||
|
# === Write Videoscape Header ===
|
||||||
|
file.write("GOUR\n")
|
||||||
|
file.write("%d\n" % len(mesh.verts))
|
||||||
|
|
||||||
|
# === Write Vertex List & Vertex Colors ===
|
||||||
|
for i in range(len(mesh.verts)):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts")
|
||||||
|
file.write("% f % f % f 0x" % tuple(mesh.verts[i].co))
|
||||||
|
for j in range(len(vcols[i])):
|
||||||
|
file.write("%02X" % vcols[i][j])
|
||||||
|
file.write("\n")
|
||||||
|
|
||||||
|
# === Write Face List ===
|
||||||
|
for i in range(len(mesh.faces)):
|
||||||
|
if not i%100 and mod_flags.show_progress:
|
||||||
|
Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces")
|
||||||
|
file.write("%d " % len(mesh.faces[i].v)) # numfaceverts
|
||||||
|
for j in range(len(mesh.faces[i].v)):
|
||||||
|
file.write("%d " % mesh.faces[i].v[j].index)
|
||||||
|
file.write("\n")
|
||||||
|
|
||||||
|
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
|
||||||
|
file.close()
|
||||||
|
#end = time.clock()
|
||||||
|
#seconds = " in %.2f %s" % (end-start, "seconds")
|
||||||
|
message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
|
||||||
|
mod_meshtools.print_boxed(message)
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# === Vector Operations for Vertex Colors ===
|
||||||
|
# ===========================================
|
||||||
|
vcolor_add = lambda u, v: [u[0]+v[0], u[1]+v[1], u[2]+v[2], u[3]+v[3]]
|
||||||
|
vcolor_div = lambda u, s: [u[0]/s, u[1]/s, u[2]/s, u[3]/s]
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# === Average All Vertex Colors (Fast) ===
|
||||||
|
# ========================================
|
||||||
|
def average_vertexcolors(mesh, debug=0):
|
||||||
|
vertexcolors = {}
|
||||||
|
for i in range(len(mesh.faces)): # get all vcolors that share this vertex
|
||||||
|
if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors")
|
||||||
|
for j in range(len(mesh.faces[i].v)):
|
||||||
|
index = mesh.faces[i].v[j].index
|
||||||
|
color = mesh.faces[i].col[j]
|
||||||
|
r,g,b,a = color.r, color.g, color.b, color.a
|
||||||
|
vertexcolors.setdefault(index, []).append([r,g,b,a])
|
||||||
|
if debug: print 'before'; vcprint(vertexcolors)
|
||||||
|
|
||||||
|
for i in range(len(vertexcolors)): # average them
|
||||||
|
if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
|
||||||
|
vcolor = [0,0,0,0] # rgba
|
||||||
|
for j in range(len(vertexcolors[i])):
|
||||||
|
vcolor = vcolor_add(vcolor, vertexcolors[i][j])
|
||||||
|
shared = len(vertexcolors[i])
|
||||||
|
vertexcolors[i] = vcolor_div(vcolor, shared)
|
||||||
|
if debug: print 'after'; vcprint(vertexcolors)
|
||||||
|
return vertexcolors
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# === Average all Vertex Colors Slow 1 ===
|
||||||
|
# ========================================
|
||||||
|
def average_vertexcolors_slow_1(mesh, debug=0):
|
||||||
|
vertexcolors = []
|
||||||
|
i = 0
|
||||||
|
for vertex in mesh.verts:
|
||||||
|
if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
|
||||||
|
i += 1
|
||||||
|
vcolor = [0,0,0,0] # rgba
|
||||||
|
shared = 0
|
||||||
|
for face in mesh.faces:
|
||||||
|
if vertex in face.v:
|
||||||
|
index = face.v.index(vertex)
|
||||||
|
color = face.col[index]
|
||||||
|
r,g,b,a = color.r, color.g, color.b, color.a
|
||||||
|
vcolor = vcolor_add(vcolor, [r,g,b,a])
|
||||||
|
shared += 1
|
||||||
|
if not shared: print "Error, vertex %d is not shared." % i; shared += 1
|
||||||
|
vertexcolors.append(vcolor_div(vcolor, shared))
|
||||||
|
if debug: print 'after'; vcprint(vertexcolors)
|
||||||
|
return vertexcolors
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# === Average all Vertex Colors Slow 2 ===
|
||||||
|
# ========================================
|
||||||
|
def average_vertexcolors_slow_2(mesh, debug=0):
|
||||||
|
vertexcolors = []
|
||||||
|
for i in range(len(mesh.verts)):
|
||||||
|
if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
|
||||||
|
vcolor = [0,0,0,0] # rgba
|
||||||
|
shared = 0
|
||||||
|
for j in range(len(mesh.faces)):
|
||||||
|
if mesh.verts[i] in mesh.faces[j].v:
|
||||||
|
index = mesh.faces[j].v.index(mesh.verts[i])
|
||||||
|
color = mesh.faces[j].col[index]
|
||||||
|
r,g,b,a = color.r, color.g, color.b, color.a
|
||||||
|
vcolor = vcolor_add(vcolor, [r,g,b,a])
|
||||||
|
shared += 1
|
||||||
|
vertexcolors.append(vcolor_div(vcolor, shared))
|
||||||
|
if debug: print 'after'; vcprint(vertexcolors)
|
||||||
|
return vertexcolors
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# === Average all Vertex Colors Slow 3 ===
|
||||||
|
# ========================================
|
||||||
|
def average_vertexcolors_slow_3(mesh, debug=0):
|
||||||
|
vertexcolors = []
|
||||||
|
for i in range(len(mesh.verts)):
|
||||||
|
if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
|
||||||
|
vcolor = [0,0,0,0] # rgba
|
||||||
|
shared = 0
|
||||||
|
for j in range(len(mesh.faces)):
|
||||||
|
if len(mesh.faces[j].v) == 4:
|
||||||
|
v1,v2,v3,v4 = mesh.faces[j].v
|
||||||
|
faceverts = v1.index, v2.index, v3.index, v4.index
|
||||||
|
else:
|
||||||
|
v1,v2,v3 = mesh.faces[j].v
|
||||||
|
faceverts = v1.index, v2.index, v3.index
|
||||||
|
|
||||||
|
if i in faceverts:
|
||||||
|
index = mesh.faces[j].v.index(mesh.verts[i])
|
||||||
|
color = mesh.faces[j].col[index]
|
||||||
|
r,g,b,a = color.r, color.g, color.b, color.a
|
||||||
|
vcolor = vcolor_add(vcolor, [r,g,b,a])
|
||||||
|
shared += 1
|
||||||
|
vertexcolors.append(vcolor_div(vcolor, shared))
|
||||||
|
if debug: print 'after'; vcprint(vertexcolors)
|
||||||
|
return vertexcolors
|
||||||
|
|
||||||
|
def fs_callback(filename):
|
||||||
|
if filename.find('.obj', -4) <= 0: filename += '.VIDEOSCAPE.obj'
|
||||||
|
write(filename)
|
||||||
|
|
||||||
|
Blender.Window.FileSelector(fs_callback, "Videoscape Export")
|
||||||
|
|
||||||
|
|
||||||
|
# filename = "VIDEOSCAPE_" + objname + ".obj"
|
||||||
|
# filename = 'nul'
|
||||||
|
# file = open(filename, "wb")
|
||||||
|
# debug = 0
|
||||||
|
# time_functions = 1
|
||||||
|
# time_loop = 0
|
||||||
|
#
|
||||||
|
# if time_functions:
|
||||||
|
# funcs = [ average_vertexcolors,
|
||||||
|
# average_vertexcolors_slow_1,
|
||||||
|
# average_vertexcolors_slow_2,
|
||||||
|
# average_vertexcolors_slow_3 ]
|
||||||
|
#
|
||||||
|
# print
|
||||||
|
# for func in funcs:
|
||||||
|
# start = time.clock()
|
||||||
|
# vcols = func(mesh, debug)
|
||||||
|
# end = time.clock()
|
||||||
|
# seconds = "in %.2f %s" % (end-start, "seconds")
|
||||||
|
# print func.__name__, "finished in", seconds
|
||||||
|
#
|
||||||
|
# elif time_loop:
|
||||||
|
# total = 0
|
||||||
|
# loops = 6
|
||||||
|
# for i in range(loops):
|
||||||
|
# start = time.clock()
|
||||||
|
# vcols = average_vertexcolors(mesh, debug)
|
||||||
|
# end = time.clock()
|
||||||
|
# total += (end-start)
|
||||||
|
# print "Total: %5.2f Avg: %.2f " % (total, total/loops)
|
||||||
|
# else:
|
||||||
|
# start = time.clock()
|
||||||
|
# vcols = average_vertexcolors(mesh, debug)
|
||||||
|
|
||||||
|
# # =====================================
|
||||||
|
# # === Print Vertex Colors for Debug ===
|
||||||
|
# # =====================================
|
||||||
|
# def vcprint(data):
|
||||||
|
# print type(data)
|
||||||
|
# for i in range(len(data)):
|
||||||
|
# print "%2d" % i,
|
||||||
|
# for j in range(len(data[i])):
|
||||||
|
# try:
|
||||||
|
# print "[%3d %3d %3d %3d]" % tuple(data[i][j]), # before
|
||||||
|
# except:
|
||||||
|
# print "[%3d]" % data[i][j], # after
|
||||||
|
# print
|
||||||
|
# print
|
||||||
|
#
|
||||||
984
release/scripts/wrl2export.py
Normal file
984
release/scripts/wrl2export.py
Normal file
@@ -0,0 +1,984 @@
|
|||||||
|
#!BPY
|
||||||
|
""" Registration info for Blender menus:
|
||||||
|
Name: 'VRML 2.0'
|
||||||
|
Blender: 232
|
||||||
|
Group: 'Export'
|
||||||
|
Submenu: 'All objects...' all
|
||||||
|
Submenu: 'Only selected objects...' selected
|
||||||
|
Tooltip: 'Export to VRML2 (.wrl) file.'
|
||||||
|
"""
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
# VRML2 exporter for blender 2.28a or above
|
||||||
|
#
|
||||||
|
# Source: http://blender.kimballsoftware.com/
|
||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# Authors: Rick Kimball with much inspiration
|
||||||
|
# from the forum at www.elysiun.com
|
||||||
|
# and irc://irc.freenode.net/blenderchat
|
||||||
|
# Ken Miller and Steve Matthews (Added Camera Support)
|
||||||
|
#
|
||||||
|
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
#
|
||||||
|
# Copyright (C) 2003,2004: Rick Kimball rick@vrmlworld.net
|
||||||
|
#
|
||||||
|
# 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 *****
|
||||||
|
#
|
||||||
|
# To use script:
|
||||||
|
# 1.) load this file in the text window.
|
||||||
|
# (press SHIFT+F11, Open New via Datablock button)
|
||||||
|
# 2.) make sure your mouse is over the text edit window and
|
||||||
|
# run this script. (press ALT+P)
|
||||||
|
# Or:
|
||||||
|
# copy to the scripts directory and it will appear in the
|
||||||
|
# export list. (Needs 2.32 or higher)
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
# a.) output filename is same as current blender file with .wrl extension
|
||||||
|
# b.) error messages go to the Blender DOS console window
|
||||||
|
#
|
||||||
|
# The latest version of this python export script:
|
||||||
|
# http://blender.kimballsoftware.com/
|
||||||
|
#
|
||||||
|
# If you like this script, try using http://vrmlworld.net/
|
||||||
|
# to show off your VRML world.
|
||||||
|
#
|
||||||
|
# 2004-01-19 by Rick Kimball <rick@vrmlworld.net>
|
||||||
|
# o added sub menus and file selector dialog
|
||||||
|
#
|
||||||
|
# 2004-01-17 by Rick Kimball <rick@vrmlworld.net>
|
||||||
|
# o add meta comments so script will appear in export menu list
|
||||||
|
#
|
||||||
|
# 2003-11-01 by Rick Kimball <rick@vrmlworld.net>
|
||||||
|
# o fixed issues related to Lamp object and 2.28a API.
|
||||||
|
#
|
||||||
|
# 2003-07-19 by Rick Kimball <rick@vrmlworld.net>
|
||||||
|
# o made compatible with new Python API in 2.28
|
||||||
|
#
|
||||||
|
# 2003-01-16 by Ken Miller - with math help from Steve Matthews :)
|
||||||
|
# o Added support for exporting cameras out of Blender
|
||||||
|
# o Sets the name of the camera as the object name
|
||||||
|
# o sets the description of the camera as the object name,
|
||||||
|
# which should be modified to something meaningful
|
||||||
|
# o sets the position and orientation
|
||||||
|
#
|
||||||
|
# 2003-01-19 Rick Kimball <rick@vrmlworld.net>
|
||||||
|
# o Added Support For PointLight, SpotLight and DirectionalLight using Lamps
|
||||||
|
# o Creates multi singlesided or doublesided IFS
|
||||||
|
# o Creates IndexedLineSets if DrawTypes is WIRE instead of Shaded
|
||||||
|
#
|
||||||
|
# 2003-02-03 Rick Kimball <rick@vrmlworld.net>
|
||||||
|
# o attempts to catch exceptions for empty objects
|
||||||
|
#
|
||||||
|
# 2003-02-04 Rick Kimball <rick@vrmlworld.net>
|
||||||
|
# o fixed file overwrite problem when blender filename is all uppercase
|
||||||
|
#
|
||||||
|
# 2003-02-08 Rick Kimball <rick@vrmlworld.net>
|
||||||
|
# o cleanStr() creates valid VRML DEF names even if object.name
|
||||||
|
# is zero length or uses VRML reserved names or characters
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
# Known Issue:
|
||||||
|
# o doesn't handle multiple materials (don't use material indices)
|
||||||
|
# o doesn't handle multiple UV textures on a single mesh. (create a mesh for each texture)
|
||||||
|
# o material colors need work
|
||||||
|
# o spotlight softness needs work
|
||||||
|
# o can't get the texture array associated with material * not the UV ones
|
||||||
|
# o can't set smoothing, crease angle and mesh smoothing * setting not accesible
|
||||||
|
#
|
||||||
|
# Still Todo:
|
||||||
|
#
|
||||||
|
# - Support for material indexes
|
||||||
|
# - Automatically Split IFS when multiple UV textures found * warning only now
|
||||||
|
# - Automatically Split IFS when combination of single vs double sided
|
||||||
|
# - Automatically Split IFS when face with only 2 vertices is found should be an ILS
|
||||||
|
# - Export common coordinate map for split IFS
|
||||||
|
# - Intelligent color array vs color index
|
||||||
|
# - Support more blender objects: World
|
||||||
|
# - Figure out how to output Animation
|
||||||
|
# - Add GUI to control the following:
|
||||||
|
# o All/Layer/Object output radio button
|
||||||
|
# o Color per vertex toggle yes/no
|
||||||
|
# o Complex/Simple VRML output radio button
|
||||||
|
# o Compressed/Uncompressed output radio button
|
||||||
|
# o Decimal precision dropdown 1,2,3,4,5,6
|
||||||
|
# o IFS/Elevation Grid output radio button
|
||||||
|
# o Normals output toggle yes/no
|
||||||
|
# o Proto output toggle yes/no
|
||||||
|
# o Verbose console progress
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
from Blender import NMesh, Lamp
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
#-- module constants
|
||||||
|
radD=math.pi/180.0
|
||||||
|
rad90=90.0*radD # for rotation
|
||||||
|
rad30=30.0*radD # default crease angle
|
||||||
|
ARG=''
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#-- utility functions and classes --
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def rad2deg(v):
|
||||||
|
return round(v*180.0/math.pi,4)
|
||||||
|
|
||||||
|
def deg2rad(v):
|
||||||
|
return (v*math.pi)/180.0;
|
||||||
|
|
||||||
|
class DrawTypes:
|
||||||
|
"""Object DrawTypes enum values
|
||||||
|
BOUNDS - draw only the bounding box of the object
|
||||||
|
WIRE - draw object as a wire frame
|
||||||
|
SOLID - draw object with flat shading
|
||||||
|
SHADED - draw object with OpenGL shading
|
||||||
|
"""
|
||||||
|
BOUNDBOX = 1
|
||||||
|
WIRE = 2
|
||||||
|
SOLID = 3
|
||||||
|
SHADED = 4
|
||||||
|
TEXTURE = 5
|
||||||
|
|
||||||
|
#------------------------------------------------------
|
||||||
|
# the Blender.Object class seems to be missing this...
|
||||||
|
#------------------------------------------------------
|
||||||
|
if not hasattr(Blender.Object,'DrawTypes'):
|
||||||
|
Blender.Object.DrawTypes = DrawTypes()
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#-- VRML2Export --
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
class VRML2Export:
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def __init__(self, filename):
|
||||||
|
#--- public you can change these ---
|
||||||
|
self.verbose=1 # level of verbosity in console 0-none, 1-some, 2-most
|
||||||
|
self.cp=3 # decimals for material color values 0.000 - 1.000
|
||||||
|
self.vp=3 # decimals for vertex coordinate values 0.000 - n.000
|
||||||
|
self.tp=3 # decimals for texture coordinate values 0.000 - 1.000
|
||||||
|
self.ambientIntensity=.2
|
||||||
|
self.defCreaseAngle=rad30
|
||||||
|
self.smooth=0
|
||||||
|
|
||||||
|
#--- class private don't touch ---
|
||||||
|
self.texNames={} # dictionary of textureNames
|
||||||
|
self.matNames={} # dictionary of materiaNames
|
||||||
|
self.indentLevel=0 # keeps track of current indenting
|
||||||
|
self.filename=filename
|
||||||
|
self.file = open(filename, "w")
|
||||||
|
self.bNav=0
|
||||||
|
self.nNodeID=0
|
||||||
|
self.VRMLReserved=[ "Anchor","Appearance","Anchor","AudioClip","Background",
|
||||||
|
"Billboard", "Box", "Collision", "Color", "ColorInterpolator",
|
||||||
|
"Cone", "Coordinate", "CoordinateInterpolator", "Cylinder",
|
||||||
|
"CylinderSensor", "DirectionalLight", "ElevationGrid",
|
||||||
|
"Extrustion", "Fog", "FontStyle", "Group", "ImageTexture",
|
||||||
|
"IndexedFaceSet", "IndexedLineSet", "Inline", "LOD",
|
||||||
|
"Material", "MovieTexture", "NavigationInfo", "Normal",
|
||||||
|
"NormalInterpolator","OrientationInterpolator", "PixelTexture",
|
||||||
|
"PlaneSensor", "PointLight", "PointSet", "PositionInterpolator",
|
||||||
|
"ProxmimitySensor", "ScalarInterpolator", "Script", "Shape",
|
||||||
|
"Sound", "Sphere", "SphereSensor", "SpotLight", "Switch",
|
||||||
|
"Text", "TextureCoordinate", "TextureTransform", "TimeSensor",
|
||||||
|
"TouchSensor", "Transform", "Viewpoint", "VisibilitySensor",
|
||||||
|
"WorldInfo"
|
||||||
|
]
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
# writeHeader, export file, cleanup
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeHeader(self):
|
||||||
|
self.file.write("#VRML V2.0 utf8\n")
|
||||||
|
self.file.write("# modeled using blender3d http://blender.org/$\n")
|
||||||
|
self.file.write("# exported using wrl2export.py version $Revision$\n")
|
||||||
|
self.file.write("# get latest exporter at http://kimballsoftware.com/blender/\n\n")
|
||||||
|
|
||||||
|
def export(self, scene):
|
||||||
|
print "Info: starting VRML2 export to " + self.filename + "..."
|
||||||
|
|
||||||
|
self.writeHeader()
|
||||||
|
theObjects = []
|
||||||
|
if ARG == 'selected':
|
||||||
|
theObjects = Blender.Object.GetSelected()
|
||||||
|
else:
|
||||||
|
theObjects = scene.getChildren()
|
||||||
|
|
||||||
|
for object in theObjects:
|
||||||
|
try:
|
||||||
|
objType=object.getType()
|
||||||
|
|
||||||
|
if objType == "Mesh":
|
||||||
|
self.writeIndexedFaceSet(object, normals = 0)
|
||||||
|
elif objType == "Camera":
|
||||||
|
self.writeCameraInfo(object)
|
||||||
|
elif objType == "Lamp":
|
||||||
|
# if there is a lamp then we probably want to turn off the headlight
|
||||||
|
if self.bNav == 0:
|
||||||
|
self.writeNavigationInfo()
|
||||||
|
self.bNav=1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lamp=Lamp.Get(object.data.getName())
|
||||||
|
try:
|
||||||
|
lampType=lamp.getType()
|
||||||
|
|
||||||
|
if lampType == Lamp.Types.Lamp:
|
||||||
|
self.writePointLight(object, lamp)
|
||||||
|
elif lampType == Lamp.Types.Spot:
|
||||||
|
self.writeSpotLight(object, lamp)
|
||||||
|
elif lampType == Lamp.Types.Sun:
|
||||||
|
self.writeDirectionalLight(object, lamp)
|
||||||
|
else:
|
||||||
|
self.writeDirectionalLight(object, lamp)
|
||||||
|
#endif
|
||||||
|
except AttributeError:
|
||||||
|
print "Error: Unable to get type info for %s" % object.name
|
||||||
|
else:
|
||||||
|
print "Info: Ignoring [%s], object type [%s] not handle yet" % \
|
||||||
|
(object.name,object.getType())
|
||||||
|
#endif
|
||||||
|
except ValueError:
|
||||||
|
print "Error: object named %s has problem with accessing an attribute" % object.name
|
||||||
|
#end try
|
||||||
|
#endfor
|
||||||
|
self.cleanup()
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
self.file.close()
|
||||||
|
self.texNames={}
|
||||||
|
self.matNames={}
|
||||||
|
self.indentLevel=0
|
||||||
|
print "Info: finished VRML2 export to %s\n" % self.filename
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
# Writes out camera info as a viewpoint
|
||||||
|
# Handles orientation, position
|
||||||
|
# Use camera object name to set description
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeCameraInfo(self, object):
|
||||||
|
if self.verbose > 0:
|
||||||
|
print "Info: exporting camera named="+object.name
|
||||||
|
#endif
|
||||||
|
|
||||||
|
self.writeIndented("DEF %s Viewpoint {\n" % (self.cleanStr(object.name)), 1)
|
||||||
|
|
||||||
|
self.writeIndented("description \"%s\" \n" % (object.name))
|
||||||
|
|
||||||
|
# get the camera location, subtract 90 degress from X to orient like VRML does
|
||||||
|
loc = self.rotatePointForVRML(object.loc)
|
||||||
|
rot = [object.RotX - 1.57, object.RotY, object.RotZ]
|
||||||
|
nRot = self.rotatePointForVRML(rot)
|
||||||
|
|
||||||
|
# convert to Quaternion and to Angle Axis
|
||||||
|
Q = self.eulerToQuaternions(nRot[0], nRot[1], nRot[2])
|
||||||
|
Q1 = self.multiplyQuaternions(Q[0], Q[1])
|
||||||
|
Qf = self.multiplyQuaternions(Q1, Q[2])
|
||||||
|
angleAxis = self.quaternionToAngleAxis(Qf)
|
||||||
|
|
||||||
|
# write orientation statement
|
||||||
|
self.writeIndented("orientation %3.2f %3.2f %3.2f %3.2f\n" %
|
||||||
|
(angleAxis[0], angleAxis[1], -angleAxis[2], angleAxis[3]))
|
||||||
|
|
||||||
|
# write position statement
|
||||||
|
self.writeIndented("position %3.2f %3.2f %3.2f\n" %
|
||||||
|
(loc[0], loc[1], loc[2]))
|
||||||
|
|
||||||
|
self.writeIndented("} # Viewpoint\n", -1)
|
||||||
|
|
||||||
|
self.writeIndented("\n")
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeIndexedFaceSet(self, object, normals = 0):
|
||||||
|
if self.verbose > 0:
|
||||||
|
print "Info: exporting mesh named=["+object.name+"]"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
imageMap={} # set of used images
|
||||||
|
sided={} # 'one':cnt , 'two':cnt
|
||||||
|
vColors={} # 'multi':1
|
||||||
|
|
||||||
|
mesh=object.getData()
|
||||||
|
|
||||||
|
nIFSCnt=self.countIFSSetsNeeded(mesh, imageMap, sided, vColors)
|
||||||
|
|
||||||
|
meshName = self.cleanStr(object.name)
|
||||||
|
|
||||||
|
if nIFSCnt > 1:
|
||||||
|
self.writeIndented("DEF %s%s Group {\n" % ("G_", meshName),1)
|
||||||
|
self.writeIndented("children [\n",1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if self.verbose > 0:
|
||||||
|
print "Debug: [%s] has %d UV Textures" % (object.name, nIFSCnt)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if sided.has_key('two') and sided['two'] > 0:
|
||||||
|
bTwoSided=1
|
||||||
|
else:
|
||||||
|
bTwoSided=0
|
||||||
|
|
||||||
|
self.writeIndented("DEF %s Shape {\n" % meshName,1)
|
||||||
|
|
||||||
|
# show script debugging info
|
||||||
|
if self.verbose > 1:
|
||||||
|
self.meshToString(mesh)
|
||||||
|
print "Debug: mesh.faces["
|
||||||
|
for face in mesh.faces:
|
||||||
|
self.faceToString(face)
|
||||||
|
#endfor
|
||||||
|
print "Debug: ]"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
maters=mesh.materials
|
||||||
|
hasImageTexture=0
|
||||||
|
|
||||||
|
if len(maters) > 0 or mesh.hasFaceUV():
|
||||||
|
self.writeIndented("appearance Appearance {\n", 1)
|
||||||
|
|
||||||
|
# right now this script can only handle a single material per mesh.
|
||||||
|
if len(maters) >= 1:
|
||||||
|
mat=Blender.Material.Get(maters[0].name)
|
||||||
|
self.writeMaterial(mat, self.cleanStr(maters[0].name,'mat_'))
|
||||||
|
if len(maters) > 1:
|
||||||
|
print "Warning: mesh named %s has multiple materials" % meshName
|
||||||
|
print "Warning: only one material per object handled"
|
||||||
|
#endif
|
||||||
|
else:
|
||||||
|
self.writeIndented("material NULL\n")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#-- textures
|
||||||
|
if mesh.hasFaceUV():
|
||||||
|
for face in mesh.faces:
|
||||||
|
if (hasImageTexture == 0) and (face.image):
|
||||||
|
self.writeImageTexture(face.image.name)
|
||||||
|
hasImageTexture=1 # keep track of face texture
|
||||||
|
#endif
|
||||||
|
#endfor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
self.writeIndented("} # Appearance\n", -1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
#--
|
||||||
|
#-- IndexedFaceSet or IndexedLineSet
|
||||||
|
#
|
||||||
|
|
||||||
|
# check if object is wireframe only
|
||||||
|
if object.drawType == Blender.Object.DrawTypes.WIRE:
|
||||||
|
# user selected WIRE=2 on the Drawtype=Wire on (F9) Edit page
|
||||||
|
ifStyle="IndexedLineSet"
|
||||||
|
else:
|
||||||
|
# user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5
|
||||||
|
ifStyle="IndexedFaceSet"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
self.writeIndented("geometry %s {\n" % ifStyle, 1)
|
||||||
|
if object.drawType != Blender.Object.DrawTypes.WIRE:
|
||||||
|
if bTwoSided == 1:
|
||||||
|
self.writeIndented("solid FALSE # two sided\n")
|
||||||
|
else:
|
||||||
|
self.writeIndented("solid TRUE # one sided\n")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#---
|
||||||
|
#--- output coordinates
|
||||||
|
self.writeCoordinates(object, mesh, meshName)
|
||||||
|
|
||||||
|
if object.drawType != Blender.Object.DrawTypes.WIRE:
|
||||||
|
#---
|
||||||
|
#--- output textureCoordinates if UV texture used
|
||||||
|
if mesh.hasFaceUV():
|
||||||
|
if hasImageTexture == 1:
|
||||||
|
self.writeTextureCoordinates(mesh)
|
||||||
|
if vColors.has_key('multi'):
|
||||||
|
self.writeVertexColors(mesh) # experiment
|
||||||
|
#endif
|
||||||
|
else:
|
||||||
|
self.writeFaceColors(mesh)
|
||||||
|
#endif hasImageTexture
|
||||||
|
#endif hasFaceUV
|
||||||
|
|
||||||
|
# TBD: figure out how to get this properly
|
||||||
|
if self.smooth:
|
||||||
|
creaseAngle=self.defCreaseAngle;
|
||||||
|
self.writeIndented("creaseAngle %s\n" % creaseAngle)
|
||||||
|
else:
|
||||||
|
self.writeIndented("creaseAngle 0.0 # in radians\n")
|
||||||
|
#endif mesh.smooth
|
||||||
|
#endif WIRE
|
||||||
|
|
||||||
|
#--- output vertexColors
|
||||||
|
if mesh.hasVertexColours() and vColors.has_key('multi'):
|
||||||
|
self.writeVertexColors(mesh)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#--- output closing braces
|
||||||
|
self.writeIndented("} # %s\n" % ifStyle, -1)
|
||||||
|
self.writeIndented("} # Shape\n", -1)
|
||||||
|
|
||||||
|
if nIFSCnt > 1:
|
||||||
|
self.writeIndented("] # children\n", -1)
|
||||||
|
self.writeIndented("} # Group\n", -1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
self.writeIndented("\n")
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeCoordinates(self, object, mesh, meshName):
|
||||||
|
#-- vertices
|
||||||
|
self.writeIndented("coord DEF %s%s Coordinate {\n" % ("coord_",meshName), 1)
|
||||||
|
self.writeIndented("point [\n", 1)
|
||||||
|
meshVertexList = mesh.verts
|
||||||
|
|
||||||
|
# create vertex list and pre rotate -90 degrees X for VRML
|
||||||
|
mm=object.getMatrix()
|
||||||
|
for vertex in meshVertexList:
|
||||||
|
v=self.rotVertex(mm, vertex);
|
||||||
|
self.writeIndented("%s %s %s,\n" %
|
||||||
|
(round(v[0],self.vp),
|
||||||
|
round(v[1],self.vp),
|
||||||
|
round(v[2],self.vp) ))
|
||||||
|
#endfor
|
||||||
|
self.writeIndented("] # point\n", -1)
|
||||||
|
self.writeIndented("} # Coordinate\n", -1)
|
||||||
|
|
||||||
|
self.writeIndented("coordIndex [\n", 1)
|
||||||
|
coordIndexList=[]
|
||||||
|
for face in mesh.faces:
|
||||||
|
cordStr=""
|
||||||
|
for i in range(len(face)):
|
||||||
|
indx=meshVertexList.index(face[i])
|
||||||
|
cordStr = cordStr + "%s, " % indx
|
||||||
|
#endfor
|
||||||
|
self.writeIndented(cordStr + "-1,\n")
|
||||||
|
#endfor
|
||||||
|
self.writeIndented("] # coordIndex\n", -1)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeTextureCoordinates(self, mesh):
|
||||||
|
texCoordList=[]
|
||||||
|
texIndexList=[]
|
||||||
|
j=0
|
||||||
|
|
||||||
|
for face in mesh.faces:
|
||||||
|
for i in range(len(face)):
|
||||||
|
texIndexList.append(j)
|
||||||
|
texCoordList.append(face.uv[i])
|
||||||
|
j=j+1
|
||||||
|
#endfor
|
||||||
|
texIndexList.append(-1)
|
||||||
|
#endfor
|
||||||
|
|
||||||
|
self.writeIndented("texCoord TextureCoordinate {\n", 1)
|
||||||
|
self.writeIndented("point [\n", 1)
|
||||||
|
for i in range(len(texCoordList)):
|
||||||
|
self.writeIndented("%s %s," %
|
||||||
|
(round(texCoordList[i][0],self.tp),
|
||||||
|
round(texCoordList[i][1],self.tp))+"\n")
|
||||||
|
#endfor
|
||||||
|
self.writeIndented("] # point\n", -1)
|
||||||
|
self.writeIndented("} # texCoord\n", -1)
|
||||||
|
|
||||||
|
self.writeIndented("texCoordIndex [\n", 1)
|
||||||
|
texIndxStr=""
|
||||||
|
for i in range(len(texIndexList)):
|
||||||
|
texIndxStr = texIndxStr + "%d, " % texIndexList[i]
|
||||||
|
if texIndexList[i]==-1:
|
||||||
|
self.writeIndented(texIndxStr + "\n")
|
||||||
|
texIndxStr=""
|
||||||
|
#endif
|
||||||
|
#endfor
|
||||||
|
self.writeIndented("] # texCoordIndex\n", -1)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeFaceColors(self, mesh):
|
||||||
|
self.writeIndented("colorPerVertex FALSE\n")
|
||||||
|
self.writeIndented("color Color {\n",1)
|
||||||
|
self.writeIndented("color [\n",1)
|
||||||
|
|
||||||
|
for face in mesh.faces:
|
||||||
|
if face.col:
|
||||||
|
c=face.col[0]
|
||||||
|
if self.verbose > 1:
|
||||||
|
print "Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
aColor = self.rgbToFS(c)
|
||||||
|
self.writeIndented("%s,\n" % aColor)
|
||||||
|
#endfor
|
||||||
|
|
||||||
|
self.writeIndented("] # color\n",-1)
|
||||||
|
self.writeIndented("} # Color\n",-1)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeVertexColors(self, mesh):
|
||||||
|
self.writeIndented("colorPerVertex TRUE\n")
|
||||||
|
self.writeIndented("color Color {\n",1)
|
||||||
|
self.writeIndented("color [\n",1)
|
||||||
|
|
||||||
|
for i in range(len(mesh.verts)):
|
||||||
|
c=self.getVertexColorByIndx(mesh,i)
|
||||||
|
if self.verbose > 1:
|
||||||
|
print "Debug: vertex[%d].col r=%d g=%d b=%d" % (i, c.r, c.g, c.b)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
aColor = self.rgbToFS(c)
|
||||||
|
self.writeIndented("%s,\n" % aColor)
|
||||||
|
#endfor
|
||||||
|
|
||||||
|
self.writeIndented("] # color\n",-1)
|
||||||
|
self.writeIndented("} # Color\n",-1)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeMaterial(self, mat, matName):
|
||||||
|
# look up material name, use it if available
|
||||||
|
if self.matNames.has_key(matName):
|
||||||
|
self.writeIndented("material USE %s\n" % matName)
|
||||||
|
self.matNames[matName]+=1
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
self.matNames[matName]=1
|
||||||
|
|
||||||
|
ambient = mat.amb
|
||||||
|
diffuseR, diffuseG, diffuseB = mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2]
|
||||||
|
emisR, emisG, emisB = diffuseR*mat.emit, diffuseG*mat.emit, diffuseB*mat.emit
|
||||||
|
shininess = mat.hard/255.0
|
||||||
|
specR = mat.specCol[0]
|
||||||
|
specG = mat.specCol[1]
|
||||||
|
specB = mat.specCol[2]
|
||||||
|
transp = 1-mat.alpha
|
||||||
|
|
||||||
|
self.writeIndented("material DEF %s Material {\n" % matName, 1)
|
||||||
|
self.writeIndented("diffuseColor %s %s %s" %
|
||||||
|
(round(diffuseR,self.cp), round(diffuseG,self.cp), round(diffuseB,self.cp)) +
|
||||||
|
"\n")
|
||||||
|
self.writeIndented("ambientIntensity %s" %
|
||||||
|
(round(ambient,self.cp))+
|
||||||
|
"\n")
|
||||||
|
self.writeIndented("specularColor %s %s %s" %
|
||||||
|
(round(specR,self.cp), round(specG,self.cp), round(specB,self.cp)) +
|
||||||
|
"\n" )
|
||||||
|
self.writeIndented("emissiveColor %s %s %s" %
|
||||||
|
(round(emisR,self.cp), round(emisG,self.cp), round(emisB,self.cp)) +
|
||||||
|
"\n" )
|
||||||
|
self.writeIndented("shininess %s" %
|
||||||
|
(round(shininess,self.cp)) +
|
||||||
|
"\n" )
|
||||||
|
self.writeIndented("transparency %s" %
|
||||||
|
(round(transp,self.cp)) +
|
||||||
|
"\n")
|
||||||
|
self.writeIndented("} # Material\n",-1)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeImageTexture(self, name):
|
||||||
|
if self.texNames.has_key(name):
|
||||||
|
self.writeIndented("texture USE %s\n" % self.cleanStr(name))
|
||||||
|
self.texNames[name] += 1
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.writeIndented("texture DEF %s ImageTexture {\n" % self.cleanStr(name), 1)
|
||||||
|
self.writeIndented("url \"%s\"\n" % name)
|
||||||
|
self.writeIndented("} # ImageTexture \n",-1)
|
||||||
|
self.texNames[name] = 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeSpotLight(self, object, lamp):
|
||||||
|
safeName = self.cleanStr(object.name)
|
||||||
|
|
||||||
|
# compute cutoff and beamwidth
|
||||||
|
intensity=min(lamp.energy/1.5,1.0) # TBD: figure out the right value
|
||||||
|
|
||||||
|
beamWidth=deg2rad(lamp.spotSize)*.5;
|
||||||
|
cutOffAngle=beamWidth*.99
|
||||||
|
|
||||||
|
(dx,dy,dz)=self.computeDirection(object)
|
||||||
|
# note -dx seems to equal om[3][0]
|
||||||
|
# note -dz seems to equal om[3][1]
|
||||||
|
# note dy seems to equal om[3][2]
|
||||||
|
om = object.getMatrix()
|
||||||
|
|
||||||
|
location=self.rotVertex(om, (0,0,0));
|
||||||
|
radius = lamp.dist*math.cos(beamWidth)
|
||||||
|
self.writeIndented("DEF %s SpotLight {\n" % safeName,1)
|
||||||
|
self.writeIndented("radius %s\n" % radius )
|
||||||
|
self.writeIndented("intensity %s\n" % intensity )
|
||||||
|
self.writeIndented("beamWidth %s # lamp.spotSize %s\n" % (beamWidth, lamp.spotSize) )
|
||||||
|
self.writeIndented("cutOffAngle %s # lamp.spotBlend %s\n" % (cutOffAngle, lamp.spotBlend))
|
||||||
|
self.writeIndented("direction %s %s %s # lamp.RotX=%s RotY=%s RotZ=%s\n" % \
|
||||||
|
(round(dx,3),round(dy,3),round(dz,3),
|
||||||
|
round(rad2deg(object.RotX),3),
|
||||||
|
round(rad2deg(object.RotY),3),
|
||||||
|
round(rad2deg(object.RotZ),3)))
|
||||||
|
self.writeIndented("location %s %s %s\n" % (round(location[0],3),
|
||||||
|
round(location[1],3),
|
||||||
|
round(location[2],3)))
|
||||||
|
self.writeIndented("} # SpotLight\n",-1)
|
||||||
|
|
||||||
|
# export a cone that matches the spotlight in verbose mode
|
||||||
|
if self.verbose > 1:
|
||||||
|
self.writeIndented("#generated visible spotlight cone\n")
|
||||||
|
self.writeIndented("Transform { # Spotlight Cone\n",1)
|
||||||
|
self.writeIndented("translation %s %s %s\n" % (round(location[0],3),
|
||||||
|
round(location[1],3),
|
||||||
|
round(location[2],3)))
|
||||||
|
rot = [object.RotX, object.RotY, object.RotZ]
|
||||||
|
nRot = self.rotatePointForVRML(rot)
|
||||||
|
|
||||||
|
# convert to Quaternion and to Angle Axis
|
||||||
|
Q = self.eulerToQuaternions(nRot[0], nRot[1], nRot[2])
|
||||||
|
Q1 = self.multiplyQuaternions(Q[0], Q[1])
|
||||||
|
Qf = self.multiplyQuaternions(Q1, Q[2])
|
||||||
|
angleAxis = self.quaternionToAngleAxis(Qf)
|
||||||
|
|
||||||
|
# write orientation statement
|
||||||
|
self.writeIndented("rotation %3.2f %3.2f %3.2f %3.2f\n" %
|
||||||
|
(angleAxis[0], angleAxis[1], -angleAxis[2], angleAxis[3]))
|
||||||
|
|
||||||
|
self.writeIndented("children [\n",1)
|
||||||
|
|
||||||
|
ch=radius
|
||||||
|
br=ch*math.sin(beamWidth)
|
||||||
|
self.writeIndented("Transform {\n",1)
|
||||||
|
self.writeIndented("translation 0 -%s 0\n" % (ch/2))
|
||||||
|
self.writeIndented("children ")
|
||||||
|
self.writeIndented("Collision {\n",1)
|
||||||
|
self.writeIndented("collide FALSE children Shape {\n",1)
|
||||||
|
self.writeIndented("geometry Cone { height %s bottomRadius %s }\n" % (ch, br))
|
||||||
|
self.writeIndented("appearance Appearance{\n",1)
|
||||||
|
self.writeIndented("material Material { diffuseColor 1 1 1 transparency .8 }\n")
|
||||||
|
self.writeIndented("} # Appearance\n",-1)
|
||||||
|
self.writeIndented("} # Shape\n",-1)
|
||||||
|
self.writeIndented("} # Collision\n",-1)
|
||||||
|
self.writeIndented("} # Transform visible cone \n",-1)
|
||||||
|
self.writeIndented("] # Spot children\n",-1)
|
||||||
|
self.writeIndented("} # SpotLight Cone Transform\n",-1)
|
||||||
|
#endif debug cone
|
||||||
|
self.writeIndented("\n")
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeDirectionalLight(self, object, lamp):
|
||||||
|
safeName = self.cleanStr(object.name)
|
||||||
|
|
||||||
|
intensity=min(lamp.energy/1.5, 1.0) # TBD: figure out the right value
|
||||||
|
(dx,dy,dz)=self.computeDirection(object)
|
||||||
|
|
||||||
|
self.writeIndented("DEF %s DirectionalLight {\n" % safeName,1)
|
||||||
|
self.writeIndented("ambientIntensity %s\n" % self.ambientIntensity )
|
||||||
|
self.writeIndented("intensity %s\n" % intensity )
|
||||||
|
self.writeIndented("direction %s %s %s\n" % (round(dx,4),round(dy,4),round(dz,4)))
|
||||||
|
self.writeIndented("} # DirectionalLight\n",-1)
|
||||||
|
self.writeIndented("\n")
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writePointLight(self, object, lamp):
|
||||||
|
safeName = self.cleanStr(object.name)
|
||||||
|
|
||||||
|
om = object.getMatrix()
|
||||||
|
location=self.rotVertex(om, (0,0,0));
|
||||||
|
intensity=min(lamp.energy/1.5,1.0) # TBD: figure out the right value
|
||||||
|
|
||||||
|
radius = lamp.dist
|
||||||
|
self.writeIndented("DEF %s PointLight {\n" % safeName,1)
|
||||||
|
self.writeIndented("ambientIntensity %s\n" % self.ambientIntensity )
|
||||||
|
self.writeIndented("intensity %s\n" % intensity )
|
||||||
|
self.writeIndented("location %s %s %s\n" % (round(location[0],3),
|
||||||
|
round(location[1],3),
|
||||||
|
round(location[2],3)))
|
||||||
|
self.writeIndented("radius %s\n" % radius )
|
||||||
|
self.writeIndented("} # PointLight\n",-1)
|
||||||
|
self.writeIndented("\n")
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def writeNavigationInfo(self):
|
||||||
|
self.writeIndented("NavigationInfo {\n",1)
|
||||||
|
self.writeIndented("headlight FALSE\n")
|
||||||
|
self.writeIndented("avatarSize [0.25, 1.75, 0.75]\n")
|
||||||
|
self.writeIndented("} # NavigationInfo\n",-1)
|
||||||
|
self.writeIndented("\n")
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#--- Utility methods
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def cleanStr(self, name, prefix='rsvd_'):
|
||||||
|
"""cleanStr(name,prefix) - try to create a valid VRML DEF name from object name"""
|
||||||
|
|
||||||
|
newName=name[:]
|
||||||
|
if len(newName) == 0:
|
||||||
|
self.nNodeID+=1
|
||||||
|
return "%s%d" % (prefix, self.nNodeID)
|
||||||
|
|
||||||
|
if newName in self.VRMLReserved:
|
||||||
|
newName='%s%s' % (prefix,newName)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if newName[0] in ['0','1','2','3','4','5','6','7','8','9']:
|
||||||
|
newName='%s%s' % ('_',newName)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for bad in [' ','"','#',"'",',','.','[','\\',']','{','}']:
|
||||||
|
newName=newName.replace(bad,'_')
|
||||||
|
return newName
|
||||||
|
|
||||||
|
def countIFSSetsNeeded(self, mesh, imageMap, sided, vColors):
|
||||||
|
"""
|
||||||
|
countIFFSetsNeeded() - should look at a blender mesh to determine
|
||||||
|
how many VRML IndexFaceSets or IndexLineSets are needed. A
|
||||||
|
new mesh created under the following conditions:
|
||||||
|
|
||||||
|
o - split by UV Textures / one per mesh
|
||||||
|
o - split by face, one sided and two sided
|
||||||
|
o - split by smooth and flat faces
|
||||||
|
o - split when faces only have 2 vertices * needs to be an IndexLineSet
|
||||||
|
"""
|
||||||
|
|
||||||
|
imageNameMap={}
|
||||||
|
faceMap={}
|
||||||
|
nFaceIndx=0
|
||||||
|
|
||||||
|
for face in mesh.faces:
|
||||||
|
sidename='';
|
||||||
|
if (face.mode & NMesh.FaceModes.TWOSIDE) == NMesh.FaceModes.TWOSIDE:
|
||||||
|
sidename='two'
|
||||||
|
else:
|
||||||
|
sidename='one'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if not vColors.has_key('multi'):
|
||||||
|
for face in mesh.faces:
|
||||||
|
if face.col:
|
||||||
|
c=face.col[0]
|
||||||
|
if c.r != 255 and c.g != 255 and c.b !=255:
|
||||||
|
vColors['multi']=1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endfor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if sided.has_key(sidename):
|
||||||
|
sided[sidename]+=1
|
||||||
|
else:
|
||||||
|
sided[sidename]=1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if face.image:
|
||||||
|
faceName="%s_%s" % (face.image.name, sidename);
|
||||||
|
|
||||||
|
if imageMap.has_key(faceName):
|
||||||
|
imageMap[faceName].append(face)
|
||||||
|
else:
|
||||||
|
imageMap[faceName]=[face.image.name,sidename,face]
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endfor
|
||||||
|
|
||||||
|
if self.verbose > 0:
|
||||||
|
for faceName in imageMap.keys():
|
||||||
|
ifs=imageMap[faceName]
|
||||||
|
print "Debug: faceName=%s image=%s, solid=%s facecnt=%d" % \
|
||||||
|
(faceName, ifs[0], ifs[1], len(ifs)-2)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return len(imageMap.keys())
|
||||||
|
|
||||||
|
def faceToString(self,face):
|
||||||
|
print "Debug: face.flag=0x%x (bitflags)" % face.flag
|
||||||
|
if face.flag & NMesh.FaceFlags.SELECT == NMesh.FaceFlags.SELECT:
|
||||||
|
print "Debug: face.flag.SELECT=true"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
print "Debug: face.mode=0x%x (bitflags)" % face.mode
|
||||||
|
if (face.mode & NMesh.FaceModes.TWOSIDE) == NMesh.FaceModes.TWOSIDE:
|
||||||
|
print "Debug: face.mode twosided"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
print "Debug: face.transp=0x%x (enum)" % face.transp
|
||||||
|
if face.transp == NMesh.FaceTranspModes.SOLID:
|
||||||
|
print "Debug: face.transp.SOLID"
|
||||||
|
#
|
||||||
|
|
||||||
|
if face.image:
|
||||||
|
print "Debug: face.image=%s" % face.image.name
|
||||||
|
#endif
|
||||||
|
print "Debug: face.materialIndex=%d" % face.materialIndex
|
||||||
|
|
||||||
|
def getVertexColorByIndx(self, mesh, indx):
|
||||||
|
for face in mesh.faces:
|
||||||
|
j=0
|
||||||
|
for vertex in face.v:
|
||||||
|
if vertex.index == indx:
|
||||||
|
c=face.col[j]
|
||||||
|
#endif
|
||||||
|
j=j+1
|
||||||
|
#endfor
|
||||||
|
#endfor
|
||||||
|
return c
|
||||||
|
|
||||||
|
def meshToString(self,mesh):
|
||||||
|
print "Debug: mesh.hasVertexUV=%d" % mesh.hasVertexUV()
|
||||||
|
print "Debug: mesh.hasFaceUV=%d" % mesh.hasFaceUV()
|
||||||
|
print "Debug: mesh.hasVertexColours=%d" % mesh.hasVertexColours()
|
||||||
|
print "Debug: mesh.verts=%d" % len(mesh.verts)
|
||||||
|
print "Debug: mesh.faces=%d" % len(mesh.faces)
|
||||||
|
print "Debug: mesh.materials=%d" % len(mesh.materials)
|
||||||
|
|
||||||
|
def rgbToFS(self, c):
|
||||||
|
s="%s %s %s" % (
|
||||||
|
round(c.r/255.0,self.cp),
|
||||||
|
round(c.g/255.0,self.cp),
|
||||||
|
round(c.b/255.0,self.cp))
|
||||||
|
return s
|
||||||
|
|
||||||
|
def computeDirection(self, object):
|
||||||
|
x,y,z=(0,-1.0,0) # point down
|
||||||
|
ax,ay,az = (object.RotX,object.RotZ,object.RotY)
|
||||||
|
|
||||||
|
# rot X
|
||||||
|
x1=x
|
||||||
|
y1=y*math.cos(ax)-z*math.sin(ax)
|
||||||
|
z1=y*math.sin(ax)+z*math.cos(ax)
|
||||||
|
|
||||||
|
# rot Y
|
||||||
|
x2=x1*math.cos(ay)+z1*math.sin(ay)
|
||||||
|
y2=y1
|
||||||
|
z2=z1*math.cos(ay)-x1*math.sin(ay)
|
||||||
|
|
||||||
|
# rot Z
|
||||||
|
x3=x2*math.cos(az)-y2*math.sin(az)
|
||||||
|
y3=x2*math.sin(az)+y2*math.cos(az)
|
||||||
|
z3=z2
|
||||||
|
|
||||||
|
return [x3,y3,z3]
|
||||||
|
|
||||||
|
|
||||||
|
# swap Y and Z to handle axis difference between Blender and VRML
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def rotatePointForVRML(self, v):
|
||||||
|
x = v[0]
|
||||||
|
y = v[2]
|
||||||
|
z = -v[1]
|
||||||
|
|
||||||
|
vrmlPoint=[x, y, z]
|
||||||
|
return vrmlPoint
|
||||||
|
|
||||||
|
def rotVertex(self, mm, v):
|
||||||
|
lx,ly,lz=v[0],v[1],v[2]
|
||||||
|
gx=(mm[0][0]*lx + mm[1][0]*ly + mm[2][0]*lz) + mm[3][0]
|
||||||
|
gy=((mm[0][2]*lx + mm[1][2]*ly+ mm[2][2]*lz) + mm[3][2])
|
||||||
|
gz=-((mm[0][1]*lx + mm[1][1]*ly + mm[2][1]*lz) + mm[3][1])
|
||||||
|
rotatedv=[gx,gy,gz]
|
||||||
|
return rotatedv
|
||||||
|
|
||||||
|
def writeIndented(self, s, inc=0):
|
||||||
|
if inc < 1:
|
||||||
|
self.indentLevel = self.indentLevel + inc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
spaces=""
|
||||||
|
for x in xrange(self.indentLevel):
|
||||||
|
spaces = spaces + " "
|
||||||
|
#endfor
|
||||||
|
self.file.write(spaces + s)
|
||||||
|
|
||||||
|
if inc > 0:
|
||||||
|
self.indentLevel = self.indentLevel + inc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# Converts a Euler to three new Quaternions
|
||||||
|
# Angles of Euler are passed in as radians
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def eulerToQuaternions(self, x, y, z):
|
||||||
|
Qx = [math.cos(x/2), math.sin(x/2), 0, 0]
|
||||||
|
Qy = [math.cos(y/2), 0, math.sin(y/2), 0]
|
||||||
|
Qz = [math.cos(z/2), 0, 0, math.sin(z/2)]
|
||||||
|
|
||||||
|
quaternionVec=[Qx,Qy,Qz]
|
||||||
|
return quaternionVec
|
||||||
|
|
||||||
|
# Multiply two Quaternions together to get a new Quaternion
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def multiplyQuaternions(self, Q1, Q2):
|
||||||
|
result = [((Q1[0] * Q2[0]) - (Q1[1] * Q2[1]) - (Q1[2] * Q2[2]) - (Q1[3] * Q2[3])),
|
||||||
|
((Q1[0] * Q2[1]) + (Q1[1] * Q2[0]) + (Q1[2] * Q2[3]) - (Q1[3] * Q2[2])),
|
||||||
|
((Q1[0] * Q2[2]) + (Q1[2] * Q2[0]) + (Q1[3] * Q2[1]) - (Q1[1] * Q2[3])),
|
||||||
|
((Q1[0] * Q2[3]) + (Q1[3] * Q2[0]) + (Q1[1] * Q2[2]) - (Q1[2] * Q2[1]))]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Convert a Quaternion to an Angle Axis (ax, ay, az, angle)
|
||||||
|
# angle is in radians
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
def quaternionToAngleAxis(self, Qf):
|
||||||
|
scale = math.pow(Qf[1],2) + math.pow(Qf[2],2) + math.pow(Qf[3],2)
|
||||||
|
ax = Qf[1]
|
||||||
|
ay = Qf[2]
|
||||||
|
az = Qf[3]
|
||||||
|
|
||||||
|
if scale > .0001:
|
||||||
|
ax/=scale
|
||||||
|
ay/=scale
|
||||||
|
az/=scale
|
||||||
|
#endif
|
||||||
|
|
||||||
|
angle = 2 * math.acos(Qf[0])
|
||||||
|
|
||||||
|
result = [ax, ay, az, angle]
|
||||||
|
return result
|
||||||
|
|
||||||
|
def file_callback(filename):
|
||||||
|
if filename.find('.wrl', -4) < 0: filename += '.wrl'
|
||||||
|
wrlexport=VRML2Export(filename)
|
||||||
|
scene = Blender.Scene.getCurrent()
|
||||||
|
wrlexport.export(scene)
|
||||||
|
#enddef
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
# main routine
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
try:
|
||||||
|
ARG = __script__['arg'] # user selected argument
|
||||||
|
except:
|
||||||
|
print "older version"
|
||||||
|
|
||||||
|
if Blender.Get('version') < 225:
|
||||||
|
print "Warning: VRML2 export failed, wrong blender version!"
|
||||||
|
print " You aren't running blender version 2.25 or greater"
|
||||||
|
print " download a newer version from http://blender.org/"
|
||||||
|
else:
|
||||||
|
if ARG == 'all' or ARG == 'selected':
|
||||||
|
Blender.Window.FileSelector(file_callback,"Save VRML 2.0")
|
||||||
|
else:
|
||||||
|
baseFileName=Blender.Get('filename')
|
||||||
|
if baseFileName.find('.') != -1:
|
||||||
|
dots=Blender.Get('filename').split('.')[0:-1]
|
||||||
|
else:
|
||||||
|
dots=[baseFileName]
|
||||||
|
#endif
|
||||||
|
dots+=["wrl"]
|
||||||
|
vrmlFile=".".join(dots)
|
||||||
|
|
||||||
|
file_callback(vrmlFile)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -396,8 +396,6 @@ int BPY_txt_do_python(struct SpaceText* st)
|
|||||||
|
|
||||||
if (!st->text) return 0;
|
if (!st->text) return 0;
|
||||||
|
|
||||||
PyErr_Clear();
|
|
||||||
|
|
||||||
/* check if this text is already running */
|
/* check if this text is already running */
|
||||||
while (script) {
|
while (script) {
|
||||||
if (!strcmp(script->id.name+2, st->text->id.name+2)) {
|
if (!strcmp(script->id.name+2, st->text->id.name+2)) {
|
||||||
@@ -488,8 +486,6 @@ int BPY_menu_do_python(short menutype, int event)
|
|||||||
|
|
||||||
if (!pym) return 0;
|
if (!pym) return 0;
|
||||||
|
|
||||||
PyErr_Clear();
|
|
||||||
|
|
||||||
if (pym->version > G.version)
|
if (pym->version > G.version)
|
||||||
notice ("Version mismatch: script was written for Blender %d. "
|
notice ("Version mismatch: script was written for Blender %d. "
|
||||||
"It may fail with yours: %d.", pym->version, G.version);
|
"It may fail with yours: %d.", pym->version, G.version);
|
||||||
@@ -632,6 +628,11 @@ void BPY_free_finished_script(Script *script)
|
|||||||
{
|
{
|
||||||
if (!script) return;
|
if (!script) return;
|
||||||
|
|
||||||
|
if (PyErr_Occurred()) { /* if script ended after filesel */
|
||||||
|
PyErr_Print(); /* eventual errors are handled now */
|
||||||
|
error ("Python script error: check console");
|
||||||
|
}
|
||||||
|
|
||||||
free_libblock(&G.main->script, script);
|
free_libblock(&G.main->script, script);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,63 +12,66 @@ scrollbar, plus support for text drawing. It also includes keyboard keys and
|
|||||||
mouse button code values in its dictionary (print dir(Blender.Draw)).
|
mouse button code values in its dictionary (print dir(Blender.Draw)).
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
import Blender
|
import Blender
|
||||||
from Blender import Draw, BGL
|
from Blender import Draw, BGL
|
||||||
#
|
|
||||||
mystring = ""
|
|
||||||
mymsg = ""
|
|
||||||
toggle = 0
|
|
||||||
#
|
|
||||||
def event(evt, val): # the function to handle input events
|
|
||||||
global mystring, mymsg
|
|
||||||
|
|
||||||
if not val: # val = 0: it's a key/mbutton release
|
mystring = ""
|
||||||
if evt in [Draw.LEFTMOUSE, Draw.MIDDLEMOUSE, Draw.RIGHTMOUSE]:
|
mymsg = ""
|
||||||
mymsg = "You released a mouse button."
|
toggle = 0
|
||||||
Draw.Redraw(1)
|
|
||||||
return
|
|
||||||
|
|
||||||
if evt == Draw.ESCKEY:
|
def event(evt, val): # the function to handle input events
|
||||||
Draw.Exit() # exit when user presses ESC
|
global mystring, mymsg
|
||||||
return
|
|
||||||
|
|
||||||
elif Draw.AKEY <= evt <= Draw.ZKEY: mystring += chr(evt)
|
if not val: # val = 0: it's a key/mbutton release
|
||||||
elif evt == Draw.SPACEKEY: mystring += ' '
|
if evt in [Draw.LEFTMOUSE, Draw.MIDDLEMOUSE, Draw.RIGHTMOUSE]:
|
||||||
elif evt == Draw.BACKSPACEKEY and len(mystring):
|
mymsg = "You released a mouse button."
|
||||||
mystring = mystring[:-1]
|
Draw.Redraw(1)
|
||||||
else: return # this is important: only re-register if an event was caught
|
return
|
||||||
|
|
||||||
Draw.Register(gui, event, button_event) # re-register to stay in the loop
|
if evt == Draw.ESCKEY:
|
||||||
#
|
Draw.Exit() # exit when user presses ESC
|
||||||
def button_event(evt): # the function to handle Draw Button events
|
return
|
||||||
global mymsg, toggle
|
|
||||||
if evt == 1:
|
elif Draw.AKEY <= evt <= Draw.ZKEY: mystring += chr(evt)
|
||||||
mymsg = "You pressed the toggle button."
|
elif evt == Draw.SPACEKEY: mystring += ' '
|
||||||
toggle = 1 - toggle
|
elif evt == Draw.BACKSPACEKEY and len(mystring):
|
||||||
Draw.Redraw(1)
|
mystring = mystring[:-1]
|
||||||
else:
|
else: return # no need to redraw if nothing changed
|
||||||
Draw.Register(gui, event, button_event)
|
|
||||||
#
|
Draw.Redraw(1)
|
||||||
def gui(): # the function to draw the screen
|
|
||||||
global mystring, mymsg, toggle
|
def button_event(evt): # the function to handle Draw Button events
|
||||||
if len(mystring) > 90: mystring = ""
|
global mymsg, toggle
|
||||||
BGL.glClearColor(0,0,1,1)
|
if evt == 1:
|
||||||
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
|
mymsg = "You pressed the toggle button."
|
||||||
BGL.glColor3f(1,1,1)
|
toggle = 1 - toggle
|
||||||
Draw.Toggle("Toggle", 1, 10, 10, 55, 20, toggle,"A toggle button")
|
Draw.Redraw(1)
|
||||||
BGL.glRasterPos2i(72, 16)
|
|
||||||
if toggle: toggle_state = "down"
|
def gui(): # the function to draw the screen
|
||||||
else: toggle_state = "up"
|
global mystring, mymsg, toggle
|
||||||
Draw.Text("The toggle button is %s." % toggle_state, "small")
|
if len(mystring) > 90: mystring = ""
|
||||||
BGL.glRasterPos2i(10, 230)
|
BGL.glClearColor(0,0,1,1)
|
||||||
Draw.Text("Type letters from a to z, ESC to leave.")
|
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
|
||||||
BGL.glRasterPos2i(20, 200)
|
BGL.glColor3f(1,1,1)
|
||||||
Draw.Text(mystring)
|
Draw.Toggle("Toggle", 1, 10, 10, 55, 20, toggle,"A toggle button")
|
||||||
BGL.glColor3f(1,0.4,0.3)
|
BGL.glRasterPos2i(72, 16)
|
||||||
BGL.glRasterPos2i(340, 70)
|
if toggle: toggle_state = "down"
|
||||||
Draw.Text(mymsg, "tiny")
|
else: toggle_state = "up"
|
||||||
#
|
Draw.Text("The toggle button is %s." % toggle_state, "small")
|
||||||
Draw.Register(gui, event, button_event) # registering the 3 callbacks
|
BGL.glRasterPos2i(10, 230)
|
||||||
|
Draw.Text("Type letters from a to z, ESC to leave.")
|
||||||
|
BGL.glRasterPos2i(20, 200)
|
||||||
|
Draw.Text(mystring)
|
||||||
|
BGL.glColor3f(1,0.4,0.3)
|
||||||
|
BGL.glRasterPos2i(340, 70)
|
||||||
|
Draw.Text(mymsg, "tiny")
|
||||||
|
|
||||||
|
Draw.Register(gui, event, button_event) # registering the 3 callbacks
|
||||||
|
|
||||||
|
@note: The example above was fixed to call Draw.Register only once. It's
|
||||||
|
not necessary to re-register the callbacks, they will stay until Draw.Exit
|
||||||
|
is called. It's enough to redraw the screen when a relevant event is caught.
|
||||||
|
Apologies for the confusion.
|
||||||
|
|
||||||
@warn: Inside the windowing loop (after Draw.Register() has been executed and
|
@warn: Inside the windowing loop (after Draw.Register() has been executed and
|
||||||
before Draw.Exit() is called), don't use the redraw functions from other
|
before Draw.Exit() is called), don't use the redraw functions from other
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ class Material:
|
|||||||
that range: if val < Min, then val = Min, if val > Max, then val = Max.
|
that range: if val < Min, then val = Min, if val > Max, then val = Max.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import Texture
|
||||||
|
|
||||||
def getName():
|
def getName():
|
||||||
"""
|
"""
|
||||||
Get the name of this Material object.
|
Get the name of this Material object.
|
||||||
@@ -471,3 +473,30 @@ class Material:
|
|||||||
@type nrings: int
|
@type nrings: int
|
||||||
@param nrings: The new value in [0, 24].
|
@param nrings: The new value in [0, 24].
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def setTexture(index, texture, texco, mapto):
|
||||||
|
"""
|
||||||
|
Assign a Blender Texture object to slot number 'number'.
|
||||||
|
@type index: int
|
||||||
|
@param index: material's texture index in [0, 7].
|
||||||
|
@type texture: Blender Texture
|
||||||
|
@param texture: a Blender Texture object.
|
||||||
|
@type texco: int
|
||||||
|
@param texco: optional or'ed bitflag -- defaults to TexCo.ORCO. See TexCo var in L{Texture}.
|
||||||
|
@type mapto: int
|
||||||
|
@param mapto: optional or'ed bitflag -- defaults to MapTo.COL. See MapTo var in L{Texture}.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def clearTexture(index):
|
||||||
|
"""
|
||||||
|
Clear the ith (given by 'index') texture channel of this material.
|
||||||
|
@type index: int
|
||||||
|
@param index: material's texture channel index in [0, 7].
|
||||||
|
"""
|
||||||
|
|
||||||
|
def getTextures ():
|
||||||
|
"""
|
||||||
|
Get this Material's Texture list.
|
||||||
|
@rtype: list
|
||||||
|
@return: a list of Blender Textures. None is returned for each empty texture slot.
|
||||||
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user