Posted: Tue Aug 12, 2008 1:23 pm Post subject: blender python script help
i am currently working on a track conversion from gp4 (hungaroring 2006) which i just added to svn and i need some help finishing it. the track is currently missing the surface coefficients (easy to do) and the starting grid/ pit lane markers. in gp4 these markers are drawn directly in the game as per some data files. what i would like to do is write a script which will help me create the markings in blender as meshes to be placed on top of the track. i don't know anything about writing blender scripts so i am asking here for help.
basically what needs to be done is this. given a track sector (a rectangle, so in blender i will select the four vertices) create a new mesh (another rectangle) to be positioned in the plane of the track sector (look at the z position) or a little bit above it and then be able to specify the x and y offsets from the bottom left corner and the width of the new mesh all as a fraction of the track sector dimensions.
this is a picture of what i am trying to do:
i can do this one sector at a time. so for the first sector (top one), the x and y offset will be zero and the width will be 1. for the second one the x and y offsets will be, let's say, 0.05 and the width 0.3.
can anybody help me write this script (or at least come up with some examples on how to do this). thanks.
import Blender
from Blender import Mesh
myObj = Blender.Object.GetSelected()[0]
sel=[v for v in myObj.getData().verts if v.sel==1]
for v in sel:
print "x,y,z: ", v[0], v[1], v[2]
will print the coordinates of the selected vertices but they get printed in the order they were present in the object and not the order i selected them (doesn't matter what order i selected them in, the output is always the same). any idea how to get the vertives in the order i selected them?
editmode = Window.EditMode()
if editmode: Blender.Window.EditMode(0)
me = bpy.data.meshes.new('myMesh')
myObj = Blender.Object.GetSelected()[0]
sel=[v for v in myObj.getData().verts if v.sel==1]
for v in sel:
print "x,y,z: ", v[0], v[1], v[2]
v[2] += 0.01
me.verts.extend([v])
with this script i can select a track sector and then place on top of it a new mesh with a given texture. there is no scaling or offsetting yet (the new mesh covers the whole track sector) but this could probably be worked into something that will do what i want it to do. any advice is still welcome.
can somebody write an import script into blender for joe objects? we already have an export one, it would make life so much easier. ideally one would be able to specify multiple joe objects to be imported at the same time. i need to fix the textures for hungaroring (the track textures are all mapped on individual track sectors so they show up all bunched up creating ugly visual artifacts). alternatively, if one knows an easy way of fixing the textures (other than using blender,; even with blender i am not really sure how to do it) that will be great.
Haven't tried it myself, but it looks like a commandline script that converts joe to obj. Maybe not as useful as a direct blender import, but does this help?
just tried it. the biggest problem is i can import only one object at a time. this makes it nearly impossible to import all the track objects into one blender session. second, the texture name is wrong, i had to fix it manually as it uses the joe object name appending png to it instead of reading the actual texture name (i don't know if that is stored in the object though). the biggest problem is my very limited knowledge of blender. i am still not sure how to unmap the texture from the track sector and make it span more than one sector.
Hi,
the texture name is only stored in the list.txt.
I've tried to write a script that loads joe files directly into blender and one to load the entire list.txt if the joe files are unpacked to the same directory with joepack.
I didn't succeed to get the normals right, but otherwise it seems to work.
And the faces in the track models seem to face in the opposite direction as the cars (cw vs ccw), perhaps that's because the normals are not imported, but i don't know really.
The scripts are based on the joe-exporter and md2-importer, and are my first experience with python.
import-joe.py
Code:
#!BPY
"""
Name: 'JOE (.joe)'
Blender: 239
Group: 'Import'
Tooltip: 'Import JOE file format. (.joe)'
"""
######################################################
# JOE Importer
# By: Rikard Öxler, based on JOE exporter by Joe Venzon
# and MD2 importer by Bob Holcomb
# Date: 1 NOV 08
# Ver: 0.1
######################################################
# This script imports a JOE file, textures,
# and animations from blender.
######################################################
import Blender
from Blender import Mesh, Object, sys
from Blender.BGL import *
from Blender.Draw import *
from Blender.Window import *
from Blender.Mathutils import Vector
import struct
import sys
from types import *
######################################################
# Main Body
######################################################
#returns the string from a null terminated string
def asciiz (s):
n = 0
while (ord(s[n]) != 0):
n = n + 1
return s[0:n]
######################################################
# JOE Model Constants
######################################################
JOE_MAX_TRIANGLES=4096
JOE_MAX_VERTICES=2048
JOE_MAX_TEXCOORDS=2048
JOE_MAX_FRAMES=512
JOE_MAX_SKINS=32
JOE_MAX_FRAMESIZE=(JOE_MAX_VERTICES * 4 + 128)
######################################################
# JOE data structures
######################################################
class joe_alias_triangle(object):
__slots__ = 'vertices',
binary_format="<fff" #little-endian (<), 3 Unsigned char
def load (self, file):
temp_data=file.read(struct.calcsize(self.binary_format))
data=struct.unpack(self.binary_format, temp_data)
self.num_vertices=data[0]
self.num_texcoords=data[1]
self.num_normals=data[2]
for i in xrange(0, self.num_vertices):
self.verts.append(joe_alias_triangle())
for i in xrange(0, self.num_normals):
self.normals.append(joe_alias_triangle())
for i in xrange(0, self.num_texcoords):
self.texcoords.append(joe_tex_coord())
for i in xrange(0, self.num_vertices):
self.verts[i].load(file)
#self.verts[i].dump()
for i in xrange(0, self.num_normals):
self.normals[i].load(file)
#self.normals[i].dump()
for i in xrange(0, self.num_texcoords):
self.texcoords[i].load(file)
#self.texcoords[i].dump()
return self
def dump (self):
print "JOE Alias Frame"
print "number of verts: ",self.num_vertices
print "number of texcoords",self.num_texcoords
print "number of normals ",self.num_normals
print ""
'''
#Header Structure
ident=0 #int 0 This is used to identify the file
version=0 #int 1 The version number of the file (Must be 8)
num_faces=0 #int 8 The number of faces (polygons)
num_frames=0 #int 10 The number of animation frames
'''
binary_format="<4i" #little-endian (<4> 0:
# for i in xrange(0,joe.num_skins):
# joe.skins[i].dump()
# if (Blender.sys.exists(joe.skins[i].name)):
# try: return Blender.Image.Load(joe.skins[i].name)
# except: return -1
def animate_joe(joe, mesh):
######### Animate the verts through keyframe animation
# Fast access to the meshes vertex coords
verts = [v.co for v in mesh.verts]
scale = g_scale.val
for i in xrange(1, joe.num_frames):
frame = joe.frames[i]
#update the vertices
for j in xrange(joe.num_vertices):
x=(frame.verts[j].vertices[0]) * scale
y=(frame.verts[j].vertices[1]) * scale
z=(frame.verts[j].vertices[2]) * scale
#put the vertex in the right spot
verts[j][:] = y,-x,z
mesh.insertKey(i,"absolute")
# mesh.insertKey(i)
#not really necissary, but I like playing with the frame counter
Blender.Set("curframe", i)
# Make the keys animate in the 3d view.
# key = mesh.key
# key.relative = False
# Add an IPO to teh Key
# ipo = Blender.Ipo.New('Key', 'joe')
# key.ipo = ipo
# Add a curve to the IPO
# curve = ipo.addCurve('Basis')
# Add 2 points to cycle through the frames.
# curve.append((1, 0))
# curve.append((joe.num_frames, (joe.num_frames-1)/10.0))
# curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
def load_joe(joe_filename, texture_filename):
sys.stdout.flush()
#read the file in
file=open(joe_filename,"rb")
WaitCursor(1)
DrawProgressBar(0.0, 'Loading JOE')
joe=joe_obj()
joe.load(file)
joe.dump()
file.close()
######### Creates a new mesh
mesh = Mesh.New()
uv_coord=[]
uv_list=[]
verts_extend = []
#load the textures to use later
#-1 if there is no texture to load
mesh_image=load_textures(joe, texture_filename)
if mesh_image == -1 and texture_filename:
print 'JOE Import, Warning, texture "%s" could not load'
if (mesh_image != -1 and texture_filename != ""):
size=mesh_image.getSize()
#is this really what the user wants
# if (size[0]!=256 or size[1]!=256):
# result=Blender.Draw.PupMenu("Texture map size is not 256x256, it's: "+str(size[0])+"x"+str(size[1])+": Continue?%t|Yes|No")
# if(result==2):
# Exit()
joe.skin_width=size[0]
joe.skin_height=size[1]
joe.num_skins = 1
######### Make the verts
DrawProgressBar(0.25,"Loading Vertex Data")
frame = joe.frames[0]
scale = g_scale.val
def tmp_get_vertex(i):
#use the first frame for the mesh vertices
x=(frame.verts[i].vertices[0])*scale
y=(frame.verts[i].vertices[1])*scale
z=(frame.verts[i].vertices[2])*scale
return x,y,z
def tmp_get_normal(i):
#use the first frame for the mesh vertices
x=(frame.normals[i].vertices[0])*scale
y=(frame.normals[i].vertices[1])*scale
z=(frame.normals[i].vertices[2])*scale
return x,y,z
mesh.verts.extend( [tmp_get_vertex(i) for i in xrange(0,frame.num_vertices)] )
del tmp_get_vertex
######## Make the UV list
DrawProgressBar(0.50,"Loading UV Data")
#w = float(joe.skin_width)
#h = float(joe.skin_height)
#if w <= 0.0: w = 1.0
#if h <0>blender
g_scale= Slider("Scale Factor: ", EVENT_NOEVENT, 10, 75, 210, 18,
1.0, 0.001, 10.0, 1, "Scale factor for obj Model");
def event(evt, val):
if (evt == QKEY and not val):
Blender.Draw.Exit()
def bevent(evt):
global g_joe_filename
global g_texture_filename
global EVENT_NOEVENT,EVENT_LOAD_JOE,EVENT_SAVE_JOE,EVENT_EXIT
######### Manages GUI events
if (evt==EVENT_EXIT):
Blender.Draw.Exit()
elif (evt==EVENT_CHOOSE_FILENAME):
FileSelector(filename_callback, "JOE File Selection")
elif (evt==EVENT_CHOOSE_TEXTURE):
FileSelector(texture_callback, "Texture Selection")
elif (evt==EVENT_LOAD_JOE):
if not Blender.sys.exists(g_joe_filename.val):
PupMenu('Model file does not exist')
return
else:
load_joe(g_joe_filename.val, g_texture_filename.val)
Blender.Redraw()
Blender.Draw.Exit()
return
if __name__ == '__main__':
Register(draw_gui, event, bevent)
and:
import-vdrift-list.py
Code:
#!BPY
"""
Name: 'VDrift (list.txt)'
Blender: 239
Group: 'Import'
Tooltip: 'Import VDrift tracks. (list.txt)'
"""
######################################################
# JOE Importer
# By: Rikard Öxler, based on JOE exporter by Joe Venzon
# and MD2 importer by Bob Holcomb
# Date: 1 NOV 08
# Ver: 0.1
######################################################
# This script imports a JOE file, textures,
# and animations from blender.
######################################################
import Blender
from Blender import Mesh, Object, sys
from Blender.BGL import *
from Blender.Draw import *
from Blender.Window import *
from Blender.Mathutils import Vector
import struct
import sys
from types import *
######################################################
# Main Body
######################################################
#returns the string from a null terminated string
def asciiz (s):
n = 0
while (ord(s[n]) != 0):
n = n + 1
return s[0:n]
######################################################
# JOE Model Constants
######################################################
JOE_MAX_TRIANGLES=4096
JOE_MAX_VERTICES=2048
JOE_MAX_TEXCOORDS=2048
JOE_MAX_FRAMES=512
JOE_MAX_SKINS=32
JOE_MAX_FRAMESIZE=(JOE_MAX_VERTICES * 4 + 128)
######################################################
# JOE data structures
######################################################
class joe_alias_triangle(object):
__slots__ = 'vertices',
binary_format="<fff" #little-endian (<), 3 Unsigned char
def load (self, file):
temp_data=file.read(struct.calcsize(self.binary_format))
data=struct.unpack(self.binary_format, temp_data)
self.num_vertices=data[0]
self.num_texcoords=data[1]
self.num_normals=data[2]
for i in xrange(0, self.num_vertices):
self.verts.append(joe_alias_triangle())
for i in xrange(0, self.num_normals):
self.normals.append(joe_alias_triangle())
for i in xrange(0, self.num_texcoords):
self.texcoords.append(joe_tex_coord())
for i in xrange(0, self.num_vertices):
self.verts[i].load(file)
#self.verts[i].dump()
for i in xrange(0, self.num_normals):
self.normals[i].load(file)
#self.normals[i].dump()
for i in xrange(0, self.num_texcoords):
self.texcoords[i].load(file)
#self.texcoords[i].dump()
return self
def dump (self):
print "JOE Alias Frame"
print "number of verts: ",self.num_vertices
print "number of texcoords",self.num_texcoords
print "number of normals ",self.num_normals
print ""
'''
#Header Structure
ident=0 #int 0 This is used to identify the file
version=0 #int 1 The version number of the file (Must be 8)
num_faces=0 #int 8 The number of faces (polygons)
num_frames=0 #int 10 The number of animation frames
'''
binary_format="<4i" #little-endian (<4> 0:
# for i in xrange(0,joe.num_skins):
# joe.skins[i].dump()
# if (Blender.sys.exists(joe.skins[i].name)):
# try: return Blender.Image.Load(joe.skins[i].name)
# except: return -1
def animate_joe(joe, mesh):
######### Animate the verts through keyframe animation
# Fast access to the meshes vertex coords
verts = [v.co for v in mesh.verts]
scale = g_scale.val
for i in xrange(1, joe.num_frames):
frame = joe.frames[i]
#update the vertices
for j in xrange(joe.num_vertices):
x=(frame.verts[j].vertices[0]) * scale
y=(frame.verts[j].vertices[1]) * scale
z=(frame.verts[j].vertices[2]) * scale
#put the vertex in the right spot
verts[j][:] = y,-x,z
mesh.insertKey(i,"absolute")
# mesh.insertKey(i)
#not really necissary, but I like playing with the frame counter
Blender.Set("curframe", i)
# Make the keys animate in the 3d view.
# key = mesh.key
# key.relative = False
# Add an IPO to teh Key
# ipo = Blender.Ipo.New('Key', 'joe')
# key.ipo = ipo
# Add a curve to the IPO
# curve = ipo.addCurve('Basis')
# Add 2 points to cycle through the frames.
# curve.append((1, 0))
# curve.append((joe.num_frames, (joe.num_frames-1)/10.0))
# curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
def load_joe(joe_filename, texture_filename):
#sys.stdout.flush()
#read the file in
file=open(joe_filename,"rb")
WaitCursor(1)
DrawProgressBar(0.0, 'Loading JOE')
joe=joe_obj()
joe.load(file)
joe.dump()
file.close()
######### Creates a new mesh
mesh = Mesh.New()
uv_coord=[]
uv_list=[]
verts_extend = []
#load the textures to use later
#-1 if there is no texture to load
mesh_image=load_textures(joe, texture_filename)
if mesh_image == -1 and texture_filename:
print 'JOE Import, Warning, texture "%s" could not load'
if (mesh_image != -1 and texture_filename != ""):
size=mesh_image.getSize()
#is this really what the user wants
# if (size[0]!=256 or size[1]!=256):
# result=Blender.Draw.PupMenu("Texture map size is not 256x256, it's: "+str(size[0])+"x"+str(size[1])+": Continue?%t|Yes|No")
# if(result==2):
# Exit()
joe.skin_width=size[0]
joe.skin_height=size[1]
joe.num_skins = 1
######### Make the verts
DrawProgressBar(0.25,"Loading Vertex Data")
frame = joe.frames[0]
scale = g_scale.val
def tmp_get_vertex(i):
#use the first frame for the mesh vertices
x=(frame.verts[i].vertices[0])*scale
y=(frame.verts[i].vertices[1])*scale
z=(frame.verts[i].vertices[2])*scale
return x,y,z
mesh.verts.extend( [tmp_get_vertex(i) for i in xrange(0,frame.num_vertices)] )
del tmp_get_vertex
######## Make the UV list
DrawProgressBar(0.50,"Loading UV Data")
#w = float(joe.skin_width)
#h = float(joe.skin_height)
#if w <= 0.0: w = 1.0
#if h <0>blender
g_scale= Slider("Scale Factor: ", EVENT_NOEVENT, 10, 75, 210, 18,
1.0, 0.001, 10.0, 1, "Scale factor for obj Model");
Joined: 29 Jun 2005 Posts: 2309 Location: Seattle, WA
Posted: Sun Nov 09, 2008 1:57 pm Post subject:
Oops, I forgot, the art repository is on svn.vdrift.net. I will create an account for you, username osteron. PM me a password. I added the .py files to the following repository under tools:
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum