cbarton
(cbarton)
August 27, 2003, 7:58am
1
Hi, I am writing an export script that exports to a propriatry format that uses VERTS, UV MAPPING, VERT COLOURS and VERT NORMALS.
Somebody put this nice script on blender.org that has allowed me to export verts with applied size /rot/ scale
###################
# Apply Transform #
###################
def apply_transform(verts, matrix):
x, y, z = verts
xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]
xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc
ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc
zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc
verts = [xcomponent, ycomponent, zcomponent]
return verts
## example
#for i in range(len(mesh.verts)):
# x, y, z = apply_transform(mesh.verts[i].co, matrix)
Now thats all well and good but I also need to transform the Normals allong with the verts, else I end up exporting vert normals that are arseabout.
Does anyone know of a function that opperates on the Normals also?
Things that would work-
Recalculating Normals from transformed faces.
Apply Size/rotate before export. (limiting)
Operate on current verts and return new ones.
So I supose my question could be shortened to:
How can I use the matrix of a mesh to output transformed normals in python?
theeth
(theeth)
August 27, 2003, 3:04pm
2
just apply the matrix to the normals like you apply them to the mesh’s vertice (rotation and size only, not displacement).
Martin
cbarton
(cbarton)
August 27, 2003, 3:14pm
3
Thats what I did, and it works until you squash and stretch.
###################
# Apply Transform #
###################
def apply_transform(verts, matrix):
x, y, z = verts
#xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]
xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] # + xloc
ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] # + yloc
zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] # + zloc
verts = [xcomponent, ycomponent, zcomponent]
return verts
theeth
(theeth)
August 27, 2003, 3:28pm
4
It should work. I always use a similar functions and I never add any problem.
Martin
cbarton
(cbarton)
August 27, 2003, 10:55pm
5
I will just re generate the normals on the exported files. since someof them are ytuffed up beyond fixing and there are about 120 of them to re convert.
cbarton
(cbarton)
August 28, 2003, 7:16am
6
Here is a function that takes 3 verts and returns a normal.
This will make objects look flat shaded.
######################################
# Normals need to be transformed too #
# ####################################
def apply_normal_transform(p1, p2, p3):
a = [0,0,0] # New vector.
b = [0,0,0]
a[0] = p2[0] - p1[0]
a[1] = p2[1] - p1[1]
a[2] = p2[2] - p1[2]
b[0] = p3[0] - p1[0]
b[1] = p3[1] - p1[1]
b[2] = p3[2] - p1[2]
nx = a[1]*b[2] - a[2]*b[1]
ny = a[2]*b[0] - a[0]*b[2]
nz = a[0]*b[1] - a[1]*b[0]
unitLength = 1.0
#unitLength = (abs(nx) + abs(ny) + abs(nz)) * 100.0
while abs(nx) + abs(ny) + abs(nz) > unitLength:
nx = nx *0.99
ny = ny *0.99
nz = nz *0.99
if nx == 0 and ny == 0 and nz == 0:
break
#print nx, ny, nz
#print "greater"
while abs(nx) + abs(ny) + abs(nz) < unitLength:
nx = nx /0.99
ny = ny /0.99
nz = nz /0.99
if nx == 0 and ny == 0 and nz == 0:
break
#print nx, ny, nz
#print "lesser"
return [str(nx), str(ny), str(nz)]
eeshlo
(eeshlo)
August 28, 2003, 9:47am
7
The apply_transform function without the translation part is correct, with the difference that scaling should also be removed from the matrix, ie. you need to create a rotation only matrix out of the blender matrix:
mtx = ob.getMatrix()
rmtx = [[0,0,0], [0,0,0], [0,0,0]]
for i in range(3):
for j in range(3):
sc = ob.size[i]
if sc!=0.0: sc = 1.0/sc
rmtx[i][j] = mtx[i][j] * sc
rmtx is now a rotation only 3x3 matrix, use that for your apply_transform() function above, this returns the correct normal.
Also in your code above to make a vector unit lenght, the usual method is to divide by the vector length:
def vecnorm(v):
d = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]
if d>0:
d = sqrt(d)
v[0]/=d; v[1]/=d; v[2]/=d
this will normalize a vector in place, so use it like in this example, which will also print the vector length before and after the function:
v = [7624.698, -0.26726, 123.456]
print "Vector length = ", sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
vecnorm(v)
print v
print "Vector length = ", sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
eeshlo
(eeshlo)
August 28, 2003, 10:24am
8
Just in case, don’t forget to import the math module to be able to use the sqrt function:
from math import *
cbarton
(cbarton)
August 28, 2003, 4:28pm
9
It Works!
Thanks so much!, The way I was doing it was so messy- but more to the point:
It did not work
This is a big help!.