Difference between revisions of "Talk:HowTo:Radiosity baking in Blender"

From VsWiki
Jump to: navigation, search
m (Development Script: radius)
Line 145: Line 145:
 
from math import pi,cos,sin
 
from math import pi,cos,sin
  
 
#import mod_form_elem
 
# ===================================
 
#reload(mod_form_elem)
 
# ===================================
 
#from mod_form_elem import *
 
  
 
fromObj = "Mesh.rad" # Set this to the resulting mesh from radio calcuation
 
fromObj = "Mesh.rad" # Set this to the resulting mesh from radio calcuation
Line 161: Line 155:
 
def sphere(name='SphereMesh', n=20, normals_out=1): # n= number of faces,normals_out= the normals of the faces points outwards
 
def sphere(name='SphereMesh', n=20, normals_out=1): # n= number of faces,normals_out= the normals of the faces points outwards
 
#smooth=0
 
#smooth=0
 +
radius=0.5
 
me=NMesh.GetRaw()  
 
me=NMesh.GetRaw()  
 
for i in range(0, n):  
 
for i in range(0, n):  
 
for j in range(0, n):
 
for j in range(0, n):
x=sin(j*pi*2.0/(n-1))*cos(-pi/2.0+i*pi/(n-1))*2.0
+
x=sin(j*pi*2.0/(n-1))*cos(-pi/2.0+i*pi/(n-1))*radius
y=cos(j*pi*2.0/(n-1))*(cos(-pi/2.0+i*pi/(n-1)))*2.0
+
y=cos(j*pi*2.0/(n-1))*(cos(-pi/2.0+i*pi/(n-1)))*radius
z=sin(-pi/2.0+i*pi/(n-1))*2.0
+
z=sin(-pi/2.0+i*pi/(n-1))*radius
 
v=NMesh.Vert(x,y,z)
 
v=NMesh.Vert(x,y,z)
 
me.verts.append(v)
 
me.verts.append(v)

Revision as of 16:53, 27 September 2005

Script talk

Vertex colors messed up again

Thsi topic again :( Ok, i've tried to reproduce my perfect copied vertex colors with the original blender-file and it just doesn't work (in all cases). When i use the obj file (by importing it again... as i did at work) i get a fairly good result. But when using the blender-file (basically the source file to the obj) i get the messed up VCols again. :-/ It's a bit frustrating when i have to do the rad-process over and over again, just to find out that it didn't do it right. Did you get the .blend file i sent you via mail mail? Just purge the vertex colors of the mesh on the first layer and try doing the rad-process with that mesh. I dunno what i can do to improve this behaviour, but i'll try to help where i can. --Pontiac 10:40, 26 Sep 2005 (PDT)


What the... please say you forgot to use the new script?! Do you happend to have ICQ? If you do, my number is 1949713.

I got the .blend file - it's the file I used to reproduce the bug I fixed. When I used the obj file I had no problems, even with the old script.

Why do you have to relcalculate the radiosity? Isn't it only transfering the vertex colors to the original mesh that's causing trouble? I put together a little debugging version of the script, here. It dumps some debugging info to stdout. Use it to reproduce your errornous results and send the stdout to me (at seaghost at hellokitty.com, or whatever you find suiting). Also post screendumps if you think they'd be useful in finding the problem. --tiny paintings 12:30, 26 Sep 2005 (PDT)

Maybe 'recalculate' is the wrong term... yes, transfering the vertex colors is the thing that doesn't work (or bette: it works, but there are vertices with the wrong 'shade') with the blend file, but only with the obj. I'll do some debugging with your script tomorrow. I'm pretty sure that it's just a minor problem, that i (we) just didn't see. (PS: At the time i tested the new script with the matrix transform i only had the obj available (which worked), so testing the blend file was no option at that time :-/ ) --Pontiac 15:16, 26 Sep 2005 (PDT)


I've been able to reproduce the symptoms you described, I believe. It's an accuracy issue... I'll look into it. --tiny paintings 15:40, 26 Sep 2005 (PDT)

Here's the hack (you have to mess with acc till it gets right):

...

acc = 0.001
accmul = 1/acc
		
def accmod(x,y,z,i,j):
	return (round(x*accmul)*acc, round(y*accmul)*acc, round(z*accmul)*acc, i, j)		
	
for i in range(len(me_to.faces)):
	for j in range(len(me_to.faces[i].v)):
		vert = me_to.faces[i].v[j].co
		l_to.append(accmod(vert[0], vert[1], vert[2], i, j))
			
for j in range(len(me_from.faces[i].v)):
	vert = me_from.faces[i].v[j].co
		l_from.append(accmod(vert[0], vert[1], vert[2], i, j))

...

The plan is rewriting it to be less of a hack (at the expense of quadratic running time)... But that should work, for now.


Here's a script that shouldn't be plauged by accuracy problems (well, not quite true as accuracy will always be a problem if have vertices close enough...). The downside is that it runs a lot slower. I'm working on speeding it up... (I need arrays, hints anyone?) But first I need to sleeeep! --tiny paintings 17:16, 26 Sep 2005 (PDT)


It seems to work with my .blend-testcase now. I'll test it some more today. And speed isn't really a problem since you (normally) do this once per mesh and hopefully never again after that. Or are there other scenarios? --Pontiac 00:03, 27 Sep 2005 (PDT)


Regarding arrays in python ... you might want to check out [1] and [2] Is that what you meant? --Pontiac 00:23, 27 Sep 2005 (PDT)

Possible improvments

  • Somehow change the script so that it sets the object centers correctly. Then we can remove the object->world transformation, sort on object space coords and and the vertex color copy would work even if one or both of the meshes are moved around. Not very urgent, just don't move the meshes around!

Original script

This is the original Script by tiny paintings. See the main page for the most recent version.

Warning: This script contains a serious bug and will only work if your objects origin (the little purple dot) is in the origin.

You have to pardon my python n00bness, this is all I could come up with. Feel free to improve it!

import Blender

# WHAT DOES IT DO?
# This script copies the vertex color information from one mesh
# to another, and does so correctly assuming the meshes have the
# same geometry, vertex-wise.

# IMPORTANT: Assumes meshes with exactly equal geometry, vertex-wise.

fromObj = "Mesh"  # Set this to the resulting mesh from radio calcuation
toObj = "Fuselage_default" # Set this to the name of your original, UV-mapped mesh.

me_from = Blender.Object.Get(fromObj).getData()
me_to = Blender.Object.Get(toObj).getData()

if not me_to and not me_from:
	print "ERROR: Source/destination object does not exist"

elif len(me_to.verts) != len(me_from.verts):
	print "ERROR: Source and destination objects must have the same number of vertices"
	
else:
	# make two lists sorted on coordinates,
	# containing a face and vertex index i and j respectively
	
	l_to = []
	l_from = []
	
	# format: [ (x,y,z, face index, vertex index), ... ]
	
	for i in range(len(me_to.faces)):
		for j in range(len(me_to.faces[i].v)):
			vert = me_to.faces[i].v[j].co
			l_to.append((vert[0], vert[1], vert[2], i, j))
			
		for j in range(len(me_from.faces[i].v)):
			vert = me_from.faces[i].v[j].co
			l_from.append((vert[0], vert[1], vert[2], i, j))
		
	# Sort the lists after vertex coordinates
	l_to.sort()	
	l_from.sort()
	
	for i in range(len(l_to)):
		to_f = l_to[i][3]
		from_f = l_from[i][3]
		to_v = l_to[i][4]
		from_v = l_from[i][4]
		
		me_to.faces[to_f].col[to_v] = me_from.faces[from_f].col[from_v]
			

	me_to.update()
	print "Copied vertex color information from object "+fromObj+" to object "+toObj+"."

Development Script

#!BPY

""" Registration info for Blender menus: <- these words are ignored
Name: 'Vertex Color Copy'
Blender: 232
Group: 'Object'
Tip: 'Copies the vertex color information from one object to another.'
"""

__author__ = ""
__url__ = ("blender",
"Script's homepage, http://vegastrike.sourceforge.net/wiki/HowTo:Radiosity_baking_in_Blender")
__version__ = "233"

__bpydoc__ = """\
"""

# WHAT DOES IT DO?
# This script copies the vertex color information from one mesh
# to another, and does so correctly assuming the meshes have the
# same geometry, vertex-wise.

import math
import Blender
from Blender import *
from Blender.Draw import *
from Blender.BGL import *
from math import pi,cos,sin


fromObj = "Mesh.rad"		# Set this to the resulting mesh from radio calcuation
toObj = "Mesh.orig"		# Set this to the name of your original, UV-mapped mesh.
ico_subd =50
fromObjx=Create(fromObj)
toObjx=Create(toObj)
ico_subdx=Create(ico_subd)

def sphere(name='SphereMesh', n=20, normals_out=1):	# n= number of faces,normals_out= the normals of the faces points outwards
	#smooth=0
	radius=0.5
	me=NMesh.GetRaw() 
	for i in range(0, n): 
		for j in range(0, n):
			x=sin(j*pi*2.0/(n-1))*cos(-pi/2.0+i*pi/(n-1))*radius
			y=cos(j*pi*2.0/(n-1))*(cos(-pi/2.0+i*pi/(n-1)))*radius
			z=sin(-pi/2.0+i*pi/(n-1))*radius
			v=NMesh.Vert(x,y,z)
			me.verts.append(v)
	n0=len(range(0, n))
	for i in range(0, n-1): 
		for j in range(0, n-1): 
			f=NMesh.Face() 
			if normals_out == 0:
				f.v.append(me.verts[i*n0+j])
				f.v.append(me.verts[i*n0+j+1])
				f.v.append(me.verts[(i+1)*n0+j+1])
				f.v.append(me.verts[(i+1)*n0+j])
			else:
				f.v.append(me.verts[(i+1)*n0+j])
				f.v.append(me.verts[(i+1)*n0+j+1])
				f.v.append(me.verts[i*n0+j+1])
				f.v.append(me.verts[i*n0+j])
			me.faces.append(f) 
		me.faces.append(f)
		#f.smooth=smooth
	mesh=NMesh.PutRaw(me, name, 0) 
	return mesh

def add_ico():
	#http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_modelmshapes.htm
	#http://download.blender.org/documentation/htmlI/ch26.html
	#http://blender.org/forum/viewforum.php?f=9
	#http://www.blender3d.org/documentation/237PythonDoc/
	
	selected_objects = Blender.Object.GetSelected() # gets the selected objects
	#selected_objects = Blender.Object.GetSelected()[0] # gets the first object of the selected
	#BB_big=[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]
	midpoint=[0, 0, 0]
	object_counter=0
	max=[0, 0, 0]
	min=[0, 0, 0]
	for object in selected_objects:
		object_counter=object_counter+1
		BB=object.getBoundBox()
		bb_point=[0,0,0]
		for point in BB:
			if point[0]>max[0]:
				max[0]=point[0]
			if point[1]>max[1]:
				max[1]=point[1]
			if point[2]>max[2]:
				max[2]=point[2]
			if point[0]<min[0]:
				min[0]=point[0]
			if point[1]<min[1]:
				min[1]=point[1]
			if point[2]<min[2]:
				min[2]=point[2]
			bb_point=[bb_point[0]+point[0], bb_point[1]+point[1], bb_point[2]+point[2]]			
		midpoint=[midpoint[0]+bb_point[0]/8, midpoint[1]+bb_point[1]/8, midpoint[2]+bb_point[2]/8]
		#midpoint=[midpoint[0]+object.loc[0], midpoint[1]+object.loc[1], midpoint[2]+object.loc[2]]

	if object_counter > 0:
		midpoint=[midpoint[0]/object_counter, midpoint[1]/object_counter, midpoint[2]/object_counter]
		size=[0.5*(max[0]-min[0])/object_counter, 0.5*(max[1]-min[1])/object_counter, 0.5*(max[2]-min[2])/object_counter]
	print size
	#sphere(name, type, faces)
	sphere_object = sphere('light_sphere', ico_subd, 0)
	sphere_object.setName('light_sphere')
	sphere_object.setLocation(midpoint)
	sphere_object.setSize(size)
	#make material with color:white and emmission ~0,02
	#sphere_object.setMaterials(materials)
	#if not me.materials:             # if there are no materials ...
	#newmat = Material.New()        # create one ...
	#me.materials.append(newmat)    # and append it to the mesh's list of mats

def copy_data():
	#global fromObj, toObj
	me_from = Blender.Object.Get(fromObj).getData()
	me_to = Blender.Object.Get(toObj).getData()

	if not me_to and not me_from:
		print "ERROR: Source/destination object does not exist"
		Blender.Draw.PupMenu("ERROR%t|Source/destination object does not exist")

	elif len(me_to.verts) != len(me_from.verts):
		print "ERROR: Source and destination objects must have the same number of vertices"
		Blender.Draw.PupMenu("ERROR%t|Source and destination objects must have the same number of vertices")
	
	else:
		
		# Transform objects to world space coordinates:
		me_to.transform(Blender.Object.Get(toObj).getMatrix())
		me_from.transform(Blender.Object.Get(fromObj).getMatrix())
	

		l_from = []
			
		for i in range(len(me_from.faces)):
			for j in range(len(me_from.faces[i].v)):
				vert = me_from.faces[i].v[j].co
				l_from.append((vert, i, j))

		
		#me_to.faces[to_f].col[to_v] = me_from.faces[from_f].col[from_v]
		
		def sqdist((x2,y2,z2), (x1,y1,z1)):
			return (x2-x1)**2 + (y2-y1)**2 + (z2-z1)**2
		
		
		for i in range(len(me_to.faces)):
			for j in range(len(me_to.faces[i].v)):
				# find nearest vertex in me_from:
			
				list_index = -1
				least_sqdist = 0
			
				for k in range(len(l_from)):
					d = sqdist(l_from[k][0], me_to.faces[i].v[j])
					
					if list_index < 0 or d < least_sqdist:
						least_sqdist = d
						list_index = k
					
				assert(list_index != -1)
				
				face_index = l_from[list_index][1]
				vert_index = l_from[list_index][2]
				
				me_to.faces[i].col[j] = me_from.faces[face_index].col[vert_index]
				
				del l_from[list_index]
				
		
		
			
		# Transform objects back to object space coordinates:
		me_to.transform(Blender.Object.Get(toObj).getInverseMatrix())
		me_from.transform(Blender.Object.Get(fromObj).getInverseMatrix())

		me_to.update()
		print "Copied vertex color information from object "+fromObj+" to object "+toObj+"."
		Blender.Draw.PupMenu("SUCESS%t|Copied vertex color information from object "+fromObj+" to object "+toObj+".")
  

def EVENT(evt,val):
   pass

def BUTTON(evt):
	if (evt==1):
		Exit()
	elif (evt==2):
		copy_data()
	elif (evt==3):
		add_ico()
	Blender.Redraw()

def DRAW():
	global fromObj, toObj, ico_subd, fromObjx, toObjx, ico_subdx

	glClear(GL_COLOR_BUFFER_BIT)
	glColor3f(0.1, 0.1, 0.15)    

	ligne=20
	#PushButton(name, event, x, y, width, height, tooltip=None)
	PushButton ("Exit",1,20,1,80,ligne)
	PushButton ("Copy Data",2,102,1,80,ligne)

	glRasterPos2f(20, ligne*2-10)
	Text("Vertex Color Copy")
	glRasterPos2f(20, ligne*3-5)
	Text("To")
	# String(name, event, x, y, width, height, initial, length, tooltip=None)
	toObj =		String('OB:', 999, 50, ligne*3-10, 200, 18, toObjx.val, 120, "The object to which the vertex colors should be copied." )
	
	glRasterPos2f(20, ligne*4-5)
	Text("From")
	fromObj =	String('OB:', 999, 50, ligne*4-10, 200, 18, fromObjx.val, 120, "The object from which the vertex colors should be copied." )
	
	PushButton ("Add Sphere", 3, 50, ligne*5-10, 90, ligne)
	#Slider(name, event, x, y, width, height, initial, min, max, realtime=1, tooltip=None)
	#glRasterPos2f(20, ligne*6-5)
	#Text("Sphere")
	ico_subd	=	Slider('Sphere faces:', 999, 50, ligne*6-10, 200, 18, ico_subdx.val, 20, 500, 1, "The faces of the sphere.")
	toObjx=toObj
	ico_subdx = ico_subd
	fromObjx=fromObj
	toObj=toObjx.val
	fromObj=fromObjx.val
	ico_subd = ico_subdx.val


Register(DRAW,EVENT,BUTTON)