virtualght export update

i really could use some help on the virtualight export script!

#!BPY

"""
Name: '3Dvirtualight'
Blender: 232
Group: 'Export'
Tip: 'Export to virtualight'
"""

#
#	bruteforce (Tm) VirtauLight exporter for Blender v2.12
#	version 1.3
#	by jano lukac, [email protected]
#	edit by peter lammers, [email protected]

#	The latest version can be found here:
#	here

import Blender
from Blender import NMesh, Scene, Object, Material
import os, re, sys
from math import *
from string import lower


#
# Quick start:
#
#		1. Modify the two variables below: savePath and outFile.
#			Please make sure savePath exists, and do not put extensions
#			to the outFile
#		2. Open this in Blender (if you haven't done so already)
#		3. Press alt-p over this script in Blender
#		4. Go to savePath dir and type vlight <outFile> -a 8
#		5. While you wait, read through these comments and the VirtuaLight
#			documentation
#		6. For the "GI" look, use a hemi-lamp with Y rotations:
#			-90 <= rotY => 90
#			Read the Lights section below for more info

savePath = "c:/vl/"
outFile = "file"

#
# Comments, Docs, Notes
#
#	I highly recommend you edit the output .vib and .vs files.
#	See a little further down for help with lights.

#	I expect you to read these comments.. if you don't, well, TS.

#	Running this script in blender will produce in your savePath:
#		1. $outFile.vib		# the scene
#		2. $outFile.vs		# materials
#		3. $filePath/Meshes/$mesh$appendor.vib		# mesh structure

#	Python notes:
#		If you use python > 2.0, change the "re" module to "pre" at all
#			occurances (i.e. search and replace).

#	Notes on supported Blender Objects
#	Camera:
#		If everything seems a bit skewed, change the FOV setting in this script.
#	Meshes:
#		All meshes export as TriangularPatches now, to maintain UV coords.
#		If you have stray vertices in a mesh (i.e. vertices but no face), you
#			will risk the chance of either having stray faces in the output
#			VIB or an empty Solid[] structure.  The empty Solid[] struct
#			will also result with a "Parse Error".  I currently have no way
#			to fix this, so you will have to do it manually.
#		If you get weird results, try to first "apply size/rot" to the mesh.
#		If you get a "parse error" in your .vib files, first check for an
#			empty Solid[] structure in the vib, then try renaming the
#			mesh in Blender.. stuff like "Box", "Plane", and "Sphere" are
#			reserved in VirtuaLight, and will cause these errors.
#			I made a basic attempt to fix this by prepending a "X" to every
#			name.  It's ugly, but it works -- can be changed in the Optional
#			Mods sections below.
#		SetSmooth works on both triangles and qauds; however, to make it work,
#			I had to manually convert quads to tris.  If you don't trust this,
#			please convert your mesh to triangles first.
#		If you have SetSmooth on quads, and have UV textures, then UV Textures
#			will be exported, but if you have problems, ctrl-t the mesh first.
#	Materials:
#		I default to PlainSurfaces, and just use basic settings, because,
#			although the settings are available in blender, I cannot get to
#			them via python.  You can manually transcribe them.
#		If you want to use textures, use FaceSelect mode in blender
#			to assign UV coordinates.  Then read how to apply textures
#			in the VirtauLight sepcifications PDF included with said program
#		No access to blender's SpTr yet, so use alpha to determine Kt.  I
#			default to an Index of Refraction to 1.3333 (glass), and use the
#			material "Mir" RGB sliders to affect the colors.
#		You can change specularity type in the Optional mods section below
#	Lights:
#		This is the fun one.  VirtuaLight has SO MANY lights, it's not even
#			funny.  I chose the corresponding lights based on functionality,
#			but *NOT* on name -- it's a bit confusing at fist, but you'll get
#			used to it. Here is how I translate between VirtuaLight and Blender:
#				AreaLight(bulb):	Lamp + sphere
#				AreaLight(plane):	Lamp + square (not implemented yet)
#				BlackHole:	Lamp + negative
#				DirectionalLight:	Sun
#				PointLight:	Lamp
#				SkyLight+Sunlight:	Hemi
#				SpotLight:	Spot
#			Note that "ClipEnd" will adjust VirtualLight's Falloff variable
#				(i.e. I couldn't find a suibtable value in blender)
#		The QUAD button in lights (f2) will make certain lamps Quadratic
#			instead of linear.
#		SunLight can be incredibly bright, consider commenting it out in the
#			scene vib file and using other lights instead.  The Dist value
#			affects the SunLight shadow; energy affects SkyLight intensity.
#		BlackHole element "Density" is set by lamp's Distance in blender.
#
#	KnownBugs with output mechanism:
#		The script itself should always work; however, the ouput may cause
#			parse errors with VirtuaLight (I handle most of them).
#		Stray vertices will cause either a parse error (due to an empty Solid[]
#			or extra faces in the output.  Cannot be fixed without change in
#			Blender's python API.
#		I *think* VirtuaLight will work properly if Material and Mesh names
#			are identical.  If you want to be on the safe side, make sure
#			all names in blender are unique before you export.
#
#	Changes since 1.1:
#		- added initialization for abNormals variable, as it caused fluke
#			in some cases.  Thanks to bladesman for finding it.
#	Changes since 1.0:
#		- allow for unsmoothed quads and tris to retain UV coords by exporting
#			all mesh as TriangularPatches instead of Polygon.
#		- divide by zero fix
#		- documentation fix
#
#	Todo:
#		- Possible nurbs (blender api pending?)
#		- Possible metaballs (blender api pending?)
#		- Mini gui to modify stuff like lights, change mesh type, etc.
#		- Handle basic animations
#		- Someone with programming experience could convert some
#			blender procedural textures to VirtuaLight shaders
#		- Find work.. if anyone needs a Sysadmin or Network Admin in
#			the southern california area, please contact me ;]
#


#
# Optional Modifications
#
# I default rounding numbers to 4.  If you want more precision, change this
# But you NEED rounding, otherwise you might get numbers with "e" in them
# and VirtuaLight doesn't handle that.
r = 4

# Change "specType" to tell what type of Specular Highlights you want default
# in your materials.  I default to "Phong" because I like to say,
# "BUI TUI PHONG!"
specType = 0
specHighlight = ["Phong", "Blinn", "Cook", "Reitz", "Gaussian"]

# Change append symbol.. use only [a-z][A-Z][0-9] and/or _
# This symbol is appended to all meshes and materials
appendor = "X"


#
# read further.. if you dare [maniacle laughter]
#




#
# sub functions - yes, I come from PERL
#
def multiply3x3(A, B):
	C = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
	for i in range(3):
		for j in range(3):
			for k in range(3):
				C[i][j] = C[i][j] + A[i][k]*B[k][j]
	return C

def multiply3x1(A, B):
	C = [0,0,0]
	for i in range(3):
		for j in range(3):
			C[i] = C[i] + A[i][j]*B[j]
	return C

def parallelVector(rotX, rotY, rotZ, oAxis):
	# convert to radians
	rotX = rotX * pi/180
	rotY = rotY * pi/180
	rotZ = rotZ * pi/180
	# counterclockwise rotations about given axis through angle)
	Tx = [[1, 0, 0], [0, cos(rotX), -sin(rotX)], [0, sin(rotX), cos(rotX)]]
	Ty = [[cos(rotY), 0, sin(rotY)], [0, 1, 0], [-sin(rotY), 0, cos(rotY)]]
	Tz = [[cos(rotZ), -sin(rotZ), 0], [sin(rotZ), cos(rotZ), 0], [0, 0, 1]]
	Tm = multiply3x3(multiply3x3(Tz, Ty), Tx)
	return multiply3x1(Tm, oAxis)

def calcNormal(face, verts, n):
	# If it's a quad, calculate normal from diagonal instead
	# Assume verts are sorted in circular fasion (i.e. next to each other)
	m = (3 * n) | 1    # when n=0 (tri), m=1; when n=1 (quad), m=3
	vectorU = [verts[face[0]][0] - verts[face[2]][0],
	           verts[face[0]][1] - verts[face[2]][1],
	           verts[face[0]][2] - verts[face[2]][2]]
	vectorV = [verts[face[n]][0] - verts[face[m]][0],
	           verts[face[n]][1] - verts[face[m]][1],
	           verts[face[n]][2] - verts[face[m]][2]]
	normal = [(vectorU[1] * vectorV[2]) - (vectorU[2] * vectorV[1]),
	          (vectorU[2] * vectorV[0]) - (vectorU[0] * vectorV[2]),
	          (vectorU[0] * vectorV[1]) - (vectorU[1] * vectorV[0])]
	nLength = sqrt((normal[0] ** 2) + (normal[1] ** 2) + (normal[2] ** 2))
	# divide by zero check
	if not nLength: return "stray"
	else: return (normal[0]/nLength, normal[1]/nLength, normal[2]/nLength)

def removeDot(name, printResults = 1):
	# Blender automatically names duped objects with "."  Virtual light
	# does not play well with either that or other non-word characters.
	p = re.compile("\W")
	fixedName = p.sub("_", name)
	if p.search(name):
		if printResults:
			print "%s renamed to %s..." % (name, fixedName)
	return fixedName

def prepareName(name, list, printResults = 1):
	# I felt bad for not handling reserved names, so this basically takes
	# care of that.  Just prepend a "X" to every name, and if it alread
	# exists, do it again.. hah, my first successful recursive function!
	m = re.compile("(.*?)(%s+$)" % appendor).search(name)
	if m: fixedName = lower(m.group(1)) + m.group(2)
	else: fixedName = lower(name)
	fixedName = "%s%s" % (fixedName, appendor)
	try:
		list.index(fixedName)
		fixedName = prepareName(fixedName, list, printResults)
	except:
		if printResults:
			print "%s renamed to %s..." % (name, fixedName)
	return fixedName


# variables
meshList = []
lampList = []
materialList = []
fixedMatList = []
fixedMeshList = []


#
# "Main"
#
scene = Blender.Scene.GetCurrent()

# Setup Scene VIB File
if not os.path.isdir(savePath):
	print "#
#	Sorry path %s does not exist" % savePath
	print "#	Please make sure the path is there
#"
	print "You will now see an error message:"
vibFileName = "%s%s.vib" % (savePath, outFile)
VIBFILE = open(vibFileName, "w")
VIBFILE.write("// Scene file converted from Blender by bruteforce

")


# Setup Material VS File
vsFileName = "%s%s.vs" % (savePath, outFile)
VSFILE = open(vsFileName, "w")
VSFILE.write("// Shader file converted from Blender by bruteforce

")
VSFILE.write("ReadArchive \"statics.vib\"

")

# Setup Meshes directory, files handled later
meshPath = "%sMeshes" % (savePath)
if not os.path.isdir(meshPath):
	os.mkdir(meshPath)
	print "%s does not exist, creating" % meshPath

#
# camera export
#

        camob = Blender.Scene.getCurrent().getCurrentCamera()
        cam = camObj.getData()
        camname = cam.name
        #camname = "Camera"	

	display = Blender.getDisplaySettings()
	aspect = display.yResolution / float(display.xResolution)
	print "Writing camera..."
	VIBFILE.write("Camera [
")
	VIBFILE.write("	(%s,%s,%s), " % (round(cameraObj.loc[0],r),
	                                  round(cameraObj.loc[1],r),
	                                  round(cameraObj.loc[2],r)))
	lookAt = parallelVector(cameraObj.rot[0], cameraObj.rot[1], cameraObj.rot[2], (0,0,-1))
	# (a,b,c) = (x,y,z) + t(parallel vector) where t is some factor, I use 1
	lookAt = [cameraObj.loc[0] + lookAt[0], cameraObj.loc[1] + lookAt[1], cameraObj.loc[2] + lookAt[2]]
	VIBFILE.write("(%s,%s,%s), " % (round(lookAt[0],r),
	                                round(lookAt[1],r),
	                                round(lookAt[2],r)))
	upAxis = parallelVector(cameraObj.rot[0], cameraObj.rot[1], cameraObj.rot[2], (0,1,0))
	VIBFILE.write("(%s,%s,%s)
" % (round(upAxis[0],r),
	                                round(upAxis[1],r),
	                                round(upAxis[2],r)))
	# which FoV is it, dammit!?
	VIBFILE.write("	FieldOfView %s
" % (360 * atan(aspect * 16 / camera.Lens) / pi))
	#VIBFILE.write("	FieldOfView %s
" % camera.Lens)
	VIBFILE.write("	Format(%s,%s)
"  % (display.xResolution, display.yResolution))
	# negative frame aspect ratio to prevent a mirrored image!
	# Thanks to Stephane Marty (virtualight author!) for this tip
	VIBFILE.write("	FrameAspectRatio -%s/%s
" % (display.xResolution, display.yResolution))
	VIBFILE.write("	Clipping(%s,%s)
" % (round(camera.ClSta,r), round(camera.ClEnd,r)))
	VIBFILE.write("]

")


# separate mesh and lights to nicely organize output files
# Note: materials are accessed different, wait until I'm inside the mesh export

   Objects = Object.GetSelected()
  if Objects == []:
     print("You have not selected an object!")
     returncode = 4
  else:
     for object in Objects:
        MtlList = []
        if len(Objects) > 1 or exporttype > 1:
           Transform = CreateMatrix(object, Transform)
           multiflag = 1
           
        mesh = NMesh.GetRawFromObject(object.name)
        ObjName = mesh.name
        has_uvco = mesh.hasVertexUV()

        VIBFILE.write("# Meshname:	%s
" % ObjName)

#	Blender.NMesh.Get(name):
#		meshList.append(name)
#	Blender.isLamp(name):
#		lampList.append(name)



#
# lamp export
#
for name in lampList:
	print "Writing lamp %s..." % name

	# define lights -- there's prolly a better way to do this
	vlights = ["AreaLight", "BlackHole", "DirectionalLight", "PointLight", "SkyLight", "SpotLight"]
	blights = {"Lamp": 3, "Spot": 5, "Sun": 2, "Hemi": 4}
	lampObj = Blender210.getObject(name)
	lamp = Blender210.getLamp(lampObj.data)
	lampType = blights[lamp.type]
	# note that Lamp Mode will take precedence over Lamp Type
	if lamp.mode[1] == "1": lampType = 0 # sphere->arealight+bulb
	if lamp.mode[7] == "1": lampType = 0 # square->arealight+plane
	if lamp.mode[5] == "1": lampType = 1 # negative
	# begin writing -- some will have to change
	VIBFILE.write("// Lamp: %s
" % name) # Thanks to JamesK for this one
	if lampType == 1:
		VIBFILE.write("%s (" % vlights[lampType])
		VIBFILE.write("(%s,%s,%s), %s, " % (round(lampObj.loc[0],r),
		                                    round(lampObj.loc[1],r),
		                                    round(lampObj.loc[2],r),
		                                    lamp.Dist))
		VIBFILE.write("'%s,%s,%s'" % (1 - lamp.R, 1 - lamp.G, 1 - lamp.B))
		VIBFILE.write("*%s)
" % lamp.Energ)
	if lampType == 4:
		VIBFILE.write("%s (" % vlights[lampType])
		VIBFILE.write("%s, " % (lamp.Dist * 5))
		VIBFILE.write("'%s,%s,%s', " % (lamp.R, lamp.G, lamp.B))
		VIBFILE.write("%s)
" % lamp.Energ)
		# calculate sun light
		if lampObj.rot[1] <= 90 and lampObj.rot[1] >= -90:
			degrees = round(lampObj.rot[1],r)
			hours = 12 - int(degrees / 15)
			minutes = 2 * int(degrees % 30)
			VIBFILE.write("SunLight(%02d:%02d, %s)

" % (hours, minutes, lamp.Dist))
		else: VIBFILE.write("
")
	else:
		VIBFILE.write("%s [
" % vlights[lampType])
		# separate the differences
		if lampType == 0:
			if lamp.mode[7] == "0":
				VIBFILE.write("	Bulb ((%s,%s,%s), %s)
" % (round(lampObj.loc[0],r),
				                                             round(lampObj.loc[1],r),
				                                             round(lampObj.loc[2],r),
				                                             lamp.Dist))
		elif lampType == 2:
			lightFrom = parallelVector(lampObj.rot[0], lampObj.rot[1], lampObj.rot[2], (0,0,-1))
			VIBFILE.write("	(%s,%s,%s)
" % (round(lightFrom[0],r),
			                                  round(lightFrom[1],r),
			                                  round(lightFrom[2],r)))
		elif lampType == 3:
			VIBFILE.write("	(%s,%s,%s)
" % (round(lampObj.loc[0],r),
			                                  round(lampObj.loc[1],r),
			                                  round(lampObj.loc[2],r)))
		elif lampType == 5:
			VIBFILE.write("	(%s,%s,%s), " % (round(lampObj.loc[0],r),
			                                  round(lampObj.loc[1],r),
			                                  round(lampObj.loc[2],r)))
			lightFrom = parallelVector(lampObj.rot[0], lampObj.rot[1], lampObj.rot[2], (0,0,-1))
			VIBFILE.write("(%s,%s,%s), " % (round(lightFrom[0],r),
			                                round(lightFrom[1],r),
			                                round(lightFrom[2],r)))
			VIBFILE.write("%s, " % lamp.SpoSi)
			# NOTE: this value is supposed to be "Falloff," but I couldn't find
			# a suibtable replacement in blender for it -- so using clipEnd for now
			VIBFILE.write("%s, " % lamp.ClipEnd)
			VIBFILE.write("%s
" % round(lamp.SpoBl,r))

		# put all similar attribs together here
		VIBFILE.write("	Intensity '%s,%s,%s'*%s
" % (lamp.R, lamp.G, lamp.B, lamp.Energ))
		# This one sets the quadratic thingy -- take a look at
		# equation in blender for the quad1 and quad2 settings,
		# maybe important to add as factor to INTENSITY
		if lamp.mode[0] == "1":
			VIBFILE.write("	Decay QUADRATIC
")
		if lamp.mode[6] == "1":
			VIBFILE.write("	LightingAttributes SHADOW
")
		elif lamp.mode[6] == "0" and lamp.mode[2] == "0":
			VIBFILE.write("	LightingAttributes SPECULAR
")
		if lamp.mode[7] == "0":
			VIBFILE.write("	MediaInteraction
")
			if lampType != 5 and lamp.mode[3] == "1":
				VIBFILE.write("	Glow %s
" % lamp.HaInt)
		VIBFILE.write("]

")


#
# mesh export
#
for name in meshList:
	# Check for empty meshes
	meshObj = Blender.getObject(name)
	mesh = Blender.getMesh(meshObj.data)
	faces = mesh.faces
	if not faces: continue

	# Check for "." in name, then make sure name is unique
	fixedName = removeDot(name)
	fixedName = prepareName(fixedName, fixedMeshList)
	fixedMeshList.append(fixedName)

	print "Writing mesh %s as %s..." % (name, fixedName)

	meshFileName = ("%s/%s.vib" % (meshPath, fixedName))
	MESHFILE = open(meshFileName, "w")
	MESHFILE.write("// Mesh Structure exported from Blender by bruteforce

")
	MESHFILE.write("Declare %s = Solid [
" % fixedName)
	VIBFILE.write("ReadArchive \"%s\"
" % meshFileName)
	VIBFILE.write("%s [
" % fixedName)

	materials = meshObj.materials
	vertices = mesh.vertices
	vnormals = mesh.normals
	texcoords = mesh.texcoords
	abNormals = 0

	# get a list of materials for later
	for material in materials:
		try:
			materialList.index(material)
		except:
			if material: materialList.append(material)

	# You have to add textures yourself
	if mesh.texture:
		VSFILE.write("// Mesh %s has UV Coords applied to it.  If you wish to add textures,
" % name)
		VSFILE.write("// please read the VirtauLight docs for more info on adding UV Textures

")
		print "Please read the VirtuaLight docs for adding UV Textures"

	# the j is to keep track what iteration I'm on in the
	# "for face in faces" loop so I can make sure I'm on the
	# right set of UV coords
	j = 0
	totalFaces = len(faces) - 1
	for face in faces:
		if face[3]: totalVerts = 4
		else: totalVerts = 3

		# gets us a normalized face normal
		if not face[4]:
			normals = calcNormal(face, vertices, totalVerts - 3)
			# if we have a divide by zero in normal calculation,
			# then we absolutley have a stray vertex or two
			if normals == "stray":
				totalFaces = totalFaces - 1
				abNormals = 1
				print "WARNING: stray vertices found"
				print "WARNING: output may not be as expected"
				continue

		# triangles
		if not (totalVerts - 3):
			MESHFILE.write("	Shape [TriangularPatch (")
			for i in range(totalVerts):
				MESHFILE.write("(%s,%s,%s), " % (round(vertices[face[i]][0],r),
				                                 round(vertices[face[i]][1],r),
				                                 round(vertices[face[i]][2],r)))
				# use vertex normals if smoothed, else print face normal
				if face[4]:
					MESHFILE.write("(%s,%s,%s)" % (round(vnormals[face[i]][0],r),
					                               round(vnormals[face[i]][1],r),
					                               round(vnormals[face[i]][2],r)))
				else:
					MESHFILE.write("(%s,%s,%s)" % (round(normals[0],r),
					                               round(normals[1],r),
					                               round(normals[2],r)))
				# add texcoords, if any
				if texcoords:
					MESHFILE.write(" UV=%s,%s" % (round(texcoords[j][i][0],r),
					                              round(texcoords[j][i][1],r)))
				if i != totalVerts - 1: MESHFILE.write(", ")
		# create triangle if face is QUAD
		# So who's your daddy now?
		else:
			MESHFILE.write("	Shape [TriangularPatch (")
			for i in range(totalVerts - 1):
				MESHFILE.write("(%s,%s,%s), " % (round(vertices[face[i]][0],r),
				                                 round(vertices[face[i]][1],r),
				                                 round(vertices[face[i]][2],r)))
				# use vertex normals if smoothed, else print face normal
				if face[4]:
					MESHFILE.write("(%s,%s,%s)" % (round(vnormals[face[i]][0],r),
					                               round(vnormals[face[i]][1],r),
					                               round(vnormals[face[i]][2],r)))
				else:
					MESHFILE.write("(%s,%s,%s)" % (round(normals[0],r),
					                               round(normals[1],r),
					                               round(normals[2],r)))
				# add texcoords, if any
				if texcoords:
					MESHFILE.write(" UV=%s,%s" % (round(texcoords[j][i][0],r),
					                              round(texcoords[j][i][1],r)))
				if i != totalVerts - 2:
					MESHFILE.write(", ")
				else:
					if materials and materials[face[5]]:
						fixedMatName = removeDot(materials[face[5]], 0)
						fixedMatName = prepareName(fixedMatName, materialList, 0)
						MESHFILE.write(") %s ]+
" % fixedMatName)
					else:
						MESHFILE.write(") ]+
")
			MESHFILE.write("	Shape [TriangularPatch (")
			for i in range(totalVerts - 1):
				I = i + 2
				if I > (totalVerts - 1): I = 0
				MESHFILE.write("(%s,%s,%s), " % (round(vertices[face[I]][0],r),
				                                 round(vertices[face[I]][1],r),
				                                 round(vertices[face[I]][2],r)))
				# use vertex normals if smoothed, else print face normal
				if face[4]:
					MESHFILE.write("(%s,%s,%s)" % (round(vnormals[face[I]][0],r),
					                               round(vnormals[face[I]][1],r),
					                               round(vnormals[face[I]][2],r)))
				else:
					MESHFILE.write("(%s,%s,%s)" % (round(normals[0],r),
					                               round(normals[1],r),
					                               round(normals[2],r)))
				# add texcoords, if any
				if texcoords:
					MESHFILE.write(" UV=%s,%s" % (round(texcoords[j][I][0],r),
					                              round(texcoords[j][I][1],r)))
				if I != 0: MESHFILE.write(", ")
		# if the face has material, add it here
		if materials and materials[face[5]]:
			fixedMatName = removeDot(materials[face[5]], 0)
			fixedMatName = prepareName(fixedMatName, materialList, 0)
			MESHFILE.write(") %s ]" % fixedMatName)
		else: MESHFILE.write(") ]")
		# if faces still exist, csg them with (+)
		if j == totalFaces: MESHFILE.write("
")
		elif j == totalFaces - 1 and abNormals: MESHFILE.write("
")
		else: MESHFILE.write("+
")

		j = j + 1

	abNormals = 0

	# Prints out the final material
	MESHFILE.write("]

")
	MESHFILE.close()


	# I apply the transformations DIRECT, rather than using Blender's "loc, rot, size"
	# because I was getting some weird ass results.  *shrug*
	#VIBFILE.write("	TransformationStack [
")
	VIBFILE.write("	Transform (
			%s,%s,%s,%s," \
	                             "
			%s,%s,%s,%s," \
	                             "
			%s,%s,%s,%s," \
	                             "
			%s,%s,%s,%s"  \
	                             "
		)" % (
					round(meshObj.matrix[0][0],r),
					round(meshObj.matrix[0][1],r),
					round(meshObj.matrix[0][2],r),
					round(meshObj.matrix[0][3],r),
					round(meshObj.matrix[1][0],r),
					round(meshObj.matrix[1][1],r),
					round(meshObj.matrix[1][2],r),
					round(meshObj.matrix[1][3],r),
					round(meshObj.matrix[2][0],r),
					round(meshObj.matrix[2][1],r),
					round(meshObj.matrix[2][2],r),
					round(meshObj.matrix[2][3],r),
					round(meshObj.matrix[3][0],r),
					round(meshObj.matrix[3][1],r),
					round(meshObj.matrix[3][2],r),
					round(meshObj.matrix[3][3],r)))
	#VIBFILE.write("	]
")
	VIBFILE.write("]

")


#
# material export
#
materialList.sort()
for name in materialList:
	# Check for "." in name, then make sure name is unique
	fixedName = removeDot(name)
	fixedName = prepareName(fixedName, fixedMatList)
	fixedMatList.append(fixedName)
	print "Writing material %s as %s..." % (name, fixedName)
	material = Blender210.getMaterial(name)
	VSFILE.write("Declare %s = Shader [ PlainSurface [
" % fixedName)
	VSFILE.write("	Color '%s,%s,%s'
" % (material.R, material.G, material.B))
	if material.Emit >= 0.1:
		VSFILE.write("	Ka %s
" % material.Emit)
	VSFILE.write("	Kd %s
" % material.Ref)
	VSFILE.write("	Ks (%s, '%s,%s,%s')
" % (material.Spec, material.SpecR, material.SpecG, material.SpecB))
	VSFILE.write("	%sSpecularBRDF %s
" % (specHighlight[specType], (-45*material.Hard)/254 + (45*255)/254))
	VSFILE.write("	Kt (%s, %s, '%s,%s,%s')
" % (1.0 - material.Alpha, 1.333, material.MirR, material.MirG, material.MirB))
	VSFILE.write("	]
]

")


VIBFILE.close()
VSFILE.close()

print "GI Blender... complete
"
sys.stdout.flush()

i cant get it working any clues?

their seems to be something wrong with the indentation starting from 287 (the camera stuff)

I think you need to add “else:” just before line 287 otherwise it will skip everything that comes after that.

then also something similar like the following:

scene = Blender.Scene.getCurrent()
camob = scene.getCurrentCamera()
cam = camob.getData()
camname = cam.name

display = scene.getWinSize()
aspect = float(display[1])/float(display[0])

camloc = camob.getLocation()
camlocx, camlocy, camlocz = camloc[0], camloc[1],camloc[2]

then writing the cameraposition to a file should work.

I dont have time to check the whole script right now, maybe later

Groeten,

Wim

Hi, just looked again at the camera part, and the following works without complaints from python (syntax is ok, but i don’t know if the numbers are the correct ones, since i dont know what virtualight expects)

# 
# camera export 
# 
if os.path.isdir(meshPath):
	scene = Blender.Scene.getCurrent()

	camob = scene.getCurrentCamera()
	cam = camob.getData()
	camname = cam.name

	camloc = camob.getLocation()
	camrot = camob.getEuler()
	display = scene.getWinSize()
	aspect = float(display[1])/float(display[0])

	print "Writing camera..." 
	VIBFILE.write("Camera [
")
	VIBFILE.write("	(%s,%s,%s), " % (round(camloc[0],r),
 										round(camloc[1],r),
										round(camloc[2],r)))
	lookAt = parallelVector(camrot[0], camrot[1], camrot[2], (0,0,-1))
	# (a,b,c) = (x,y,z) + t(parallel vector) where t is some factor, I use 1
	lookAt = [camloc[0] + lookAt[0], camloc[1] + lookAt[1], camloc[2] + lookAt[2]]
	VIBFILE.write("(%s,%s,%s), " % (round(lookAt[0],r),
									round(lookAt[1],r),
									round(lookAt[2],r)))
	upAxis = parallelVector(camrot[0], camrot[1], camrot[2], (0,1,0))
	VIBFILE.write("(%s,%s,%s)
" % (round(upAxis[0],r),
									round(upAxis[1],r),
									round(upAxis[2],r)))
	# which FoV is it, dammit!?
	VIBFILE.write("	FieldOfView %s
" % (360 * atan(aspect * 16 / cam.getLens()) / pi))
	#VIBFILE.write("	FieldOfView %s
" % camera.Lens)
	VIBFILE.write("	Format(%s,%s)
"  % (display[0], display[1]))
	# negative frame aspect ratio to prevent a mirrored image!
	# Thanks to Stephane Marty (virtualight author!) for this tip
	VIBFILE.write("	FrameAspectRatio -%s/%s
" % (display[0], display[1]))
	VIBFILE.write("	Clipping(%s,%s)
" % (round(cam.getClipStart(),r), round(cam.getClipEnd(),r)))
	VIBFILE.write("]

")

Greetings,

Wim

Everytime I run the script it crashes at a surtain line, giving the error
File “<string>”, line 329
if Objects == []:
________ ^ (the underscores are just to correct the position)
IndentationError: unindent does not match any outer indentation level
and even if I change it he finds another error in the line.
Maybe I need active python or something like that but i’d really like to have this script going because i’d like to test virtualight for rendering since yafray doesn’t go in the caustics rendering export area (maybe this script doesn’t either, might be pitty)
thanks anyway ^
IndentationError: unindent does not match any outer indentation level
and even if I change it he finds another error in the line.
Maybe I need active python or something like that but i’d really like to have this script going because i’d like to test virtualight for rendering since yafray doesn’t go in the caustics rendering export area (maybe this script doesn’t either, might be pitty)
thanks anyway

Hi,

That’s because the indentation in the script posted by dotblend is incorrect, make sure that from line 329 on, every line of code has an indentation that is a multiple of 3 (3,6,9,12) spaces. The following piece of code has correct indentation.

# separate mesh and lights to nicely organize output files 
# Note: materials are accessed different, wait until I'm inside the mesh export 

   Objects = Object.GetSelected() 
   if Objects == []: 
      print("You have not selected an object!") 
      returncode = 4 
   else: 
      for object in Objects: 
         MtlList = [] 
         if len(Objects) &gt; 1 or exporttype &gt; 1: 
            Transform = CreateMatrix(object, Transform) 
            multiflag = 1 
            
         mesh = NMesh.GetRawFromObject(object.name) 
         ObjName = mesh.name 
         has_uvco = mesh.hasVertexUV() 

         VIBFILE.write("# Meshname:	%s
" % ObjName) 

#   Blender.NMesh.Get(name): 
#      meshList.append(name) 
#   Blender.isLamp(name): 
#      lampList.append(name)

I also think you need a full python install to get it working (python 2.2.3).

Hope this helps,

Wim

Thanks,
But now it crashes on another line, giving the error
File “G:\Blender.blender\scripts\aaportvirtuallight.py”, line 21, in ?
import os, re, sys
ImportError: No module named os
It always crashes there, all of the scripts that have a line with ‘import os, re, sys, noise’, everyone of those scripts crashes. Maybe I need a must-have script to make it work, I don’t know (desperate, most of the scripts I have won’t work because of this :< ). I installed python 2.2.3, I don’t even know what it does or that I have to do something with to get all those scripts to work.
Thanks for reading, thanks² in case of reply
Thanks anyway
Cheerse

Hi,

If you have installed python 2.2.3 and it cannot find the module os, this probably means that your pythonpath is not set (correctly).

Have a look at the following thread https://blenderartists.org/forum/viewtopic.php?t=7723 and following the instructions.

You can check if your pythonpath is set correctly by typing the following in a text window in blender:

import sys
print sys.path

it should return something like this in the terminal/konsole:

['/usr/local/lib/python2.2', '/usr/local/lib/python2.2/plat-linux2', '/usr/local/lib/python2.2/lib-tk', '/usr/local/lib/python2.2/lib-dynload', '/usr/local/lib/python2.2/site-packages', '/usr/local/lib/python2.2/site-packages/gtk-2.0', '/usr/lib/python2.2/', '/usr/lib/python2.2/plat-linux2', '/usr/lib/python2.2/lib-tk', '/usr/lib/python2.2/lib-dynload', '/home/tuinbels/blender-2.32-linux-glibc2.2.5-i386', '/usr/lib/python2.2/site-packages', '/usr/lib/site-python', '/home/tuinbels/blender-2.32-linux-glibc2.2.5-i386/.blender/scripts']

This should prevent the script from crashing at line 21.
But does not mean that it will work, since I only updated the camera-export part of the script. And I don’t have time to update the whole script right now. You will have to contact the author (Dotblend, where are you??) of the script for that.

I hope this helps,

Wim

Hello again,
I have mistaken, I installed python2.3 and even with the pythonpath set I can’t get it to work now the error is in the os.py itself
Traceback (most recent call last):
File “G:\Blender.blender\scripts\aaportvirtuallight.py”, line 21, in ?
import os, re, sys
File “G:\PYTHON23\LIB\os.py”, line 282
yield top, dirs, nondirs
_____^
SyntaxError: invalid syntax
should I instead install python 2.2.3
I don’t know
And if take out the import os he gives
Traceback (most recent call last):
File “G:\Blender.blender\scripts\aaportvirtuallight.py”, line 21, in ?
import os, re, sys
File “G:\PYTHON23\LIB\re.py”, line 5, in ?
from sre import *
File “G:\PYTHON23\LIB\sre.py”, line 97, in ?
import sre_compile
File “G:\PYTHON23\LIB\sre_compile.py”, line 13, in ?
import _sre, sys
ImportError: Module use of python23.dll conflicts with this version of Python.
Maybe I should give it a go on 2.2.3, but since my pc is a wreck i’dd like to know if that would help cause with everything new I install my pc comes one mile closer to the junkyard.

AFAIK you definately need python 2.2.3, not 2.3
Hope that helps.

Great ! Now that Virtualight is now freeware even better.-

http://www.3dvirtualight.com/

lets update this baby
since 1.4 is out!

Yes Just what Doc ordered.

I hope you guys dont think it in terms of getting it to work with blender like yafray right now before it get fully functional exporter.

The aim should be like YabelX script. Why ?? put simply, Virtualight gets what it wants not what blender wants to give it ( unlike the current state of Yaf-blender integration). Where blender was modded to accomodate yafray and got all mixed up. Neither is perfect any more. Well at least to me.

So I wish that it should be a pure exporter. I will test my hear out to give you feedbacks. :slight_smile:

Regards,
Gaurav

does the script work now, with blender 2.37a and virtualight 1.4 and python 2.2.3 ? if yes, could please someone upload the whole script, not only all those parts above??

thx,

bastla

Do you know?
New VlirtuaLight exporter is below! :stuck_out_tongue:
(But I’m not author.)
https://blenderartists.org/forum/viewtopic.php?t=39767&start=15&postdays=0&postorder=asc
Enjoy!

thx