If anyone is interested in using ATI’s NormalMapper directly with Blender, read this post:
http://www.blender.org/modules.php?op=modload&name=phpBB2&file=viewtopic&t=5842
Sweet, I’ll have to give this a go. I tried using the other version tha can take .obj files, but most of the time it was producing invisible normal maps <sigh>.
EDIT: Just tried it, it all seems to work until I actually try to generate the normal map. The blender dos window thing did calculations (took about 10 seconds to do a 240k mesh) and ended up saying SUCCESS. I then (using the UI) went into the normal mapper, selected the models and output file name. Set the size to 256 (as a test) and ran it. It does it’s thing for a few seconds as it loads in the model, then says the normal map is completed. I open up the file in GIMP and all I have is a blank image.
Any ideas? I’d really like to get this working properly as I could really use it for the mod I’m in.
going through old threads thought i’d give this a bump
LetterRip
I installed the script, but when I ran it there was no GUI… even if I did not have an ATI card, shouldn’t the GUI still be present?
It did create a .nmf file in bpydata that was 2.4 Mb, (I was following the tutorial, except I only had 2 of the 4 “tiles” made.
I think people with sufficently recent graphics cards [as in, they support pixel shaders] should use nvidia’s tool instead
http://developer.nvidia.com/object/melody_home.html
ati’s tool seems to be more aimed towards those that might want to do this on the command line…
I was a little afraid of that, because it means I would have to export the blender model to .3ds format first, and then port it to Ogre… flying blind in the .3ds phase because I don’t happen to own 3d studio max.
I was a little afraid of that, because it means I would have to export the blender model to .3ds format first, and then port it to Ogre… flying blind in the .3ds phase because I don’t happen to own 3d studio max.[/quote]
what?
melody can load obj files, and exports them too
since it adds new uv coordinates to the object [somewhat annoying, result has multiple sets of uvs] you’ll kinda have to convert from whatever your export from melody to something that your engine can handle without loosing the second set…
edit: I forgot to mention that melody likes to export dxt [directx texture format] images…
well-behavin’ nmf pipeline done in c++ would be great …
I’ve added a GUI to the exporter so that you can do everything inside Blender now. The exporter runs as a seperate process so you can continue Blendering while the map is built.
Here is the new download: http://neuralfuzz.com/opengl/NormalMapper.zip
You can also view online help and some WIP tutorials here: http://www.neuralfuzz.com/opengl/blender/normalmapping/Help
nmf’s export fine and fast, but for some odd reason, normalmapper.exe repeatedly *causes errors … * in devil.dll … and crashes (blender and script remain un-affected).
I downloaded the zip file and moved the script into the blender script folder, but it doesnt work. It says that there was a python script error: check console. It seems to me that I did everything right but it just doesnt load. I thought that maybe I had to have a plane or something selected so i made a high poly and low poly modlel and it still didnt work…what am i not doing?
what am i not doing?
LOL … the right thing ?
Yeah i guess so…you got my hopes up there. I thought someone wrote what to do.
import Blender, sys, os, math, string
from Blender import Mathutils
from Blender.Mathutils import*
from struct import*
from Blender.BGL import*
from Blender import Draw
KEEP_SETTINGS = 1
if KEEP_SETTINGS:
try: import pickle
except:
Blender.Draw.PupMenu("Can't import pickle module!%t|Permanent settings disabled.")
KEEP_SETTINGS = 0
NmHeader = '4s1I'
NmRawTriangle = '9f 9f 6f'
ATI_NORMALMAPPER = 'C:\\NormalMapper'
configTextName = 'nmfexport.cfg'
objectMeshList = Blender.Object.Get()
HighPolyModelMenu = Draw.Create(0)
LowPolyModelMenu = Draw.Create(0)
TextureSizeMenu = Draw.Create(512)
SamplePerTexelMenu = Draw.Create(1)
BumpMapString = Draw.Create('')
NormalMapNameString = Draw.Create('NM')
pathString = Draw.Create(os.path.dirname(Blender.Get('filename')))
bumpMapToggle = Draw.Create(0)
EXEpathString = Draw.Create(ATI_NORMALMAPPER)
heightScaleNumber = Draw.Create(1.0)
boxFilterToggle = Draw.Create(1)
normalSpaceMenu = Draw.Create(0)
borderExpandMenu = Draw.Create(-1)
meshHPExported = 0
meshLPExported = 0
BUTTON_EVENT_OK = 101
BUTTON_EVENT_QUIT = 102
BUTTON_EVENT_SELECTED_HPMODELMENU = 1020
BUTTON_EVENT_SELECTED_LPMODELMENU = 1021
BUTTON_EVENT_BUILD_NORMALMAP = 1022
BUTTON_EVENT_SELECTED_TEXTURESIZE = 1023
BUTTON_EVENT_EXPORT_NMF = 1024
BUTTON_EVENT_BUMPMAPTOGGLE = 1025
BUTTON_EVENT_BUMPSTRING = 1026
BUTTON_EVENT_NORMALMAPSTRING = 1027
BUTTON_EVENT_HEIGHTSCALENUMBER = 1028
BUTTON_EVENT_BOXFILTER = 1029
BUTTON_EVENT_SAMPLEPERTEXEL = 1030
BUTTON_EVENT_NORMALSPACE = 1031
BUTTON_EVENT_BORDEREXPAND = 1032
BUTTON_EVENT_PATHSTRING = 110
BUTTON_EVENT_PATHBUTTON = 111
BUTTON_EVENT_BUMPBUTTON = 112
BUTTON_EVENT_EXEPATHSTRING = 113
BUTTON_EVENT_EXEPATHBUTTON = 114
BUTTON_EVENT_HEIGHTSCALE = 115
def saveSettings ():
global bumpMapToggle, BumpMapString, NormalMapNameString, EXEpathString
global heightScaleNumber, TextureSizeMenu, pathString, HighPolyModelMenu
global HighPolyModelMenu, LowPolyModelMenu, configTextName, boxFilterToggle
global SamplePerTexelMenu, normalSpaceMenu, borderExpandMenu
settingsDict = {}
success = 0
settingsDict['TextureSize'] = TextureSizeMenu.val
settingsDict['OutputPath'] = pathString.val
settingsDict['ExePath'] = EXEpathString.val
settingsDict['heightScale'] = heightScaleNumber.val
settingsDict['HighPolyModel'] = HighPolyModelMenu.val
settingsDict['LowPolyModel'] = LowPolyModelMenu.val
settingsDict['NormalMapName'] = NormalMapNameString.val
settingsDict['BumpMapName'] = BumpMapString.val
settingsDict['UseBumpMap'] = bumpMapToggle.val
settingsDict['BoxFilter'] = boxFilterToggle.val
settingsDict['SamplePerTexel'] = SamplePerTexelMenu.val
settingsDict['NormalSpace'] = normalSpaceMenu.val
settingsDict['BorderExpand'] = borderExpandMenu.val
if configTextName in [text.getName() for text in Blender.Text.Get()]:
oldConfigText = Blender.Text.Get(configTextName)
oldConfigText.setName(configTextName + '.old')
Blender.Text.unlink(oldConfigText)
configText = Blender.Text.New(configTextName)
configText.write('nmfexport configuration file.
This file is automatically created. Please don\'t edit this file directly.
')
try:
configText.write(pickle.dumps(settingsDict))
except:
pass
else:
success = 1
return success
def loadSettings (filename):
global bumpMapToggle, BumpMapString, NormalMapNameString, EXEpathString
global heightScaleNumber, TextureSizeMenu, pathString, HighPolyModelMenu
global HighPolyModelMenu, LowPolyModelMenu, boxFilterToggle, SamplePerTexelMenu
global normalSpaceMenu, borderExpandMenu
settingsDict = {}
success = 0
if configTextName in [text.getName() for text in Blender.Text.Get()]:
configText = Blender.Text.Get(configTextName)
try:
settingsDict = pickle.loads(string.join (configText.asLines()[4:], '
'))
except:
pass
else:
success = 1
if not success and os.path.isfile(filename):
try:
fileHandle = open (filename, 'r')
except IOError, (errno, strerror):
print "I/O Error(%s): %s" % (errno, strerror)
else:
try:
unpickler = pickle.Unpickler(fileHandle)
settingsDict = unpickler.load()
fileHandle.close()
except EOFError:
print "EOF Error"
else:
success = 1
if settingsDict.has_key('TextureSize'):
TextureSizeMenu = Blender.Draw.Create(settingsDict['TextureSize'])
if settingsDict.has_key('OutputPath'):
pathString = Blender.Draw.Create(settingsDict['OutputPath'])
if settingsDict.has_key('ExePath'):
EXEpathString = Blender.Draw.Create(settingsDict['ExePath'])
if settingsDict.has_key('heightScale'):
heightScaleNumber = Blender.Draw.Create(settingsDict['heightScale'])
if settingsDict.has_key('BumpMapName'):
BumpMapString = Blender.Draw.Create(settingsDict['BumpMapName'])
if settingsDict.has_key('UseBumpMap'):
bumpMapToggle = Blender.Draw.Create(settingsDict['UseBumpMap'])
if settingsDict.has_key('NormalMapName'):
NormalMapNameString = Blender.Draw.Create(settingsDict['NormalMapName'])
if settingsDict.has_key('HighPolyModel'):
HighPolyModelMenu = Blender.Draw.Create(settingsDict['HighPolyModel'])
if settingsDict.has_key('LowPolyModel'):
LowPolyModelMenu = Blender.Draw.Create(settingsDict['LowPolyModel'])
if settingsDict.has_key('BoxFilter'):
boxFilterToggle = Blender.Draw.Create(settingsDict['BoxFilter'])
if settingsDict.has_key('SamplePerTexel'):
SamplePerTexelMenu = Blender.Draw.Create(settingsDict['SamplePerTexel'])
if settingsDict.has_key('NormalSpace'):
normalSpaceMenu = Blender.Draw.Create(settingsDict['NormalSpace'])
if settingsDict.has_key('BorderExpand'):
borderExpandMenu = Blender.Draw.Create(settingsDict['BorderExpand'])
return success
def buildRawTriangle (f, i0, i1, i2, hasUV):
v0 = Vector(f.v[i0].co[:])
v1 = Vector(f.v[i1].co[:])
v2 = Vector(f.v[i2].co[:])
if f.smooth == 0:
n0 = n1 = n2 = Vector(f.no[:])
else:
n0 = Vector(f.v[i0].no[:])
n1 = Vector(f.v[i1].no[:])
n2 = Vector(f.v[i2].no[:])
if hasUV:
uv0 = Vector([f.uv[i0][0], f.uv[i0][1]])
uv1 = Vector([f.uv[i1][0], f.uv[i1][1]])
uv2 = Vector([f.uv[i2][0], f.uv[i2][1]])
else:
uv0 = uv1 = uv2 = Vector([0, 1])
return pack (NmRawTriangle, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, n0.x, n0.y, n0.z, n1.x, n1.y, n1.z, n2.x, n2.y, n2.z, uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y)
def splitFace (f, hasUV):
sp = ''
if len(f.v) >= 3:
sp = buildRawTriangle (f, 0, 1, 2, hasUV)
if len(f.v) == 4:
sp += buildRawTriangle (f, 2, 3, 0, hasUV)
return sp
def exportObject (obj):
dataDir = pathString.val+'\\'
outputFileName = obj.getName()+'.nmf'
print "Object :"
print outputFileName, "
"
print "outputing file to:"
print dataDir, "
"
fp = open (dataDir + outputFileName, 'wb')
ndata = obj.getData()
numTris = 0
for f in ndata.faces:
if len(f.v) >= 3:
numTris += 1
if len(f.v) == 4:
numTris += 1
print "Writing main NMF Header to file"
headersize = calcsize(NmHeader)+calcsize('I') + calcsize(NmRawTriangle) * numTris
fp.write(pack (NmHeader, 'NMF ', headersize))
print "Writing TRIS Header to file"
headersize = calcsize('I')+calcsize(NmRawTriangle) * numTris
fp.write(pack (NmHeader, 'TRIS', headersize))
fp.write(pack ('1I', numTris))
print "Writing", numTris, " Triangles to file
"
for f in ndata.faces:
fp.write(splitFace (f, ndata.hasFaceUV()))
fp.close()
return
def exportHighLowMeshesToNMF ():
global objectMeshList, HighPolyModelMenu, LowPolyModelMenu
global meshHPExported, meshLPExported
startTime = Blender.sys.time()
print
print "Starting to export selected objects
",
obj = objectMeshList[HighPolyModelMenu.val]
if obj.getType() == "Mesh":
exportObject(obj)
meshHPExported = 1
else:
print "No High Poly mesh selected so no NMF export"
meshHPExported = 0
obj = objectMeshList[LowPolyModelMenu.val]
if obj.getType() == "Mesh":
exportObject(obj)
meshLPExported = 1
else:
print "No Low Poly mesh selected so no NMF export"
meshLPExported = 0
print "took", Blender.sys.time() - startTime, "seconds"
if meshHPExported and meshLPExported:
Blender.Draw.PupMenu("ATI nmf exporter finished")
print "######## SUCCESS ########"
else:
if not meshHPExported:
Blender.Draw.PupMenu("WARNING: no High Poly Mesh exported")
if not meshLPExported:
Blender.Draw.PupMenu("WARNING: no low Poly Mesh exported")
return
def generateNormalMap ():
global bumpMapToggle, BumpMapString, NormalMapNameString, EXEpathString
global heightScaleNumber, boxFilterToggle, SamplePerTexelMenu, normalSpaceMenu
global borderExpandMenu
if EXEpathString.val != '':
dataDir = pathString.val+'\\'
textureSize = str(TextureSizeMenu.val)+' '
meshHPFileName = '"'+dataDir + objectMeshList[HighPolyModelMenu.val].getName() + '.nmf"'
meshLPFileName = '"'+dataDir + objectMeshList[LowPolyModelMenu.val].getName() + '.nmf"'
commandLine = EXEpathString.val+'\\NormalMapper.exe'
cmdLineArgs = ' -'
if boxFilterToggle.val:
cmdLineArgs += 'B'
if SamplePerTexelMenu.val > -1:
cmdLineArgs += str(SamplePerTexelMenu.val)
if normalSpaceMenu.val > 0:
cmdLineArgs += 'w'
if borderExpandMenu.val > -1:
if borderExpandMenu.val == 0:
cmdLineArgs += 'e'
elif borderExpandMenu.val == 1:
cmdLineArgs += 'E'
elif borderExpandMenu.val == 2:
cmdLineArgs += 'g'
elif borderExpandMenu.val == 3:
cmdLineArgs += 'G'
if cmdLineArgs == ' -':
cmdLineArgs = ' '
else:
cmdLineArgs += ' '
cmdLineArgs += meshLPFileName + " " + meshHPFileName + ' ' + textureSize + textureSize
if bumpMapToggle.val:
cmdLineArgs += ' "' + BumpMapString.val + '" ' + str(heightScaleNumber.val) + ' '
cmdLineArgs += '"' + dataDir + NormalMapNameString.val + '"'
print "starting ATI NormalMapper.exe:"
print commandLine, cmdLineArgs
os.spawnl (os.P_NOWAIT, commandLine, cmdLineArgs);
return
def pathSelectCallback (fileName):
global pathString
pathString = Blender.Draw.Create(os.path.dirname(fileName))
return
def EXEpathSelectCallback (fileName):
global EXEpathString
EXEpathString = Blender.Draw.Create(os.path.dirname(fileName))
return
def bumpFileSelectCallback (fileName):
global BumpMapString
BumpMapString = Blender.Draw.Create(os.path.abspath(fileName))
return
def frameDecorator (x, y, width):
glColor3f (0.5, 0.5, 0.5)
glRectf (x, y - 36, x + width, y - 16)
glColor3f (0.9, 0.9, 0.9)
glRasterPos2i (x + 85, y - 30)
Draw.Text ("ATI Normal Mapper Tool GUI", "normal")
return 20
def drawText (text, x, y):
glColor3f (0.1, 0.1, 0.1)
glRasterPos2i (x, y)
Draw.Text (text, "normal")
return x + Draw.GetStringWidth(text) + 5
def refreshGUI ():
return
def initGUI ():
if KEEP_SETTINGS:
loadSettings(Blender.Get('filename') + ".txt")
refreshGUI()
return
def exitGUI ():
if KEEP_SETTINGS:
saveSettings()
Blender.Draw.Exit()
return
def buttonCallback (event):
global eventCallback, buttonCallback
global HighPolyModelMenu, LowPolyModelMenu
global meshHPExported, meshLPExported
if (event == BUTTON_EVENT_OK):
refreshGUI()
Draw.Register (gui, eventCallback, buttonCallback)
elif (event == BUTTON_EVENT_SELECTED_HPMODELMENU):
meshHPExported = 0
Draw.Redraw(1)
elif (event == BUTTON_EVENT_SELECTED_LPMODELMENU):
meshLPExported = 0
Draw.Redraw(1)
elif (event == BUTTON_EVENT_EXPORT_NMF):
exportHighLowMeshesToNMF()
Draw.Redraw(1)
elif (event == BUTTON_EVENT_QUIT):
exitGUI()
elif (event == BUTTON_EVENT_PATHBUTTON):
Blender.Window.FileSelector (pathSelectCallback, "Export Directory", pathString.val)
Draw.Redraw(1)
elif (event == BUTTON_EVENT_EXEPATHBUTTON):
Blender.Window.FileSelector (EXEpathSelectCallback, "EXE Directory", EXEpathString.val)
Draw.Redraw(1)
elif (event == BUTTON_EVENT_BUMPBUTTON):
Blender.Window.FileSelector (bumpFileSelectCallback, "Bump Map File", BumpMapString.val)
Draw.Redraw(1)
elif (event == BUTTON_EVENT_BUMPMAPTOGGLE):
Draw.Redraw(1)
elif (event == BUTTON_EVENT_BUILD_NORMALMAP):
exportHighLowMeshesToNMF()
if meshHPExported and meshLPExported:
generateNormalMap()
Draw.Redraw(1)
return
def eventCallback (event, value):
if (value != 0):
if (event == Draw.ESCKEY):
exitGUI()
if (event == Draw.QKEY):
exitGUI()
return
def gui ():
global pathString, EXEpathString, TextureSizeMenu, BumpMapString, bumpMapToggle
global selectedObjectsList, HighPolyModelMenu, LowPolyModelMenu, NormalMapNameString
global heightScaleNumber, boxFilterToggle, SamplePerTexelMenu, normalSpaceMenu
global borderExpandMenu
guiRectBuffer = Buffer (GL_FLOAT, 4)
glGetFloatv (GL_SCISSOR_BOX, guiRectBuffer)
guiRect = [0, 0, int(guiRectBuffer.list[2]), int(guiRectBuffer.list[3])]
remainRect = guiRect[:]
remainRect[0] += 10
remainRect[1] += 10
remainRect[2] -= 10
remainRect[3] -= 10
glClearColor (0.7, 0.7, 0.7, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
remainRect[3] -= frameDecorator (remainRect[0], remainRect[3], remainRect[2] - remainRect[0])
remainRect[1] += 70
remainRect[3] -= 40
pathString = Draw.String ("Output Path: ", BUTTON_EVENT_PATHSTRING, \
10, remainRect[3] - 20, guiRect[2] - 91, 20, \
pathString.val, 255, "the directory where the mesh.nmf and normal map files are saved")
Draw.Button ("Select", BUTTON_EVENT_PATHBUTTON, guiRect[2] - 80, remainRect[3] - 20, 70, 20, "select the directory where the files are saved")
remainRect[3] -= 20
EXEpathString = Draw.String ("NormalMapper.exe Path: ", BUTTON_EVENT_EXEPATHSTRING, \
10, remainRect[3] - 20, guiRect[2] - 91, 20, \
EXEpathString.val, 255, "the directory where the ATI NormalMapper.exe is")
Draw.Button ("Select", BUTTON_EVENT_EXEPATHBUTTON, guiRect[2] - 80, remainRect[3] - 20, 70, 20, "select the directory where the NormalMapper.exe file is saved")
remainRect[3] -= 30
Draw.Button ("Quit", BUTTON_EVENT_QUIT, guiRect[2] - 110, 10, 100, 30, "quit without exporting")
objectMeshMenuName = "Meshes %t|"
objectMeshMenuIndex = 0
if (len(objectMeshList) > 0):
for object in objectMeshList:
if object.getType() == "Mesh":
objectMeshMenuName += object.getName() + " %x" + ("%d" % objectMeshMenuIndex) + "|"
objectMeshMenuIndex += 1
else:
objectMeshMenuName = "No Mesh objects found in scene! %t"
remainRect[0] = drawText ("High Poly Mesh: ", remainRect[0], remainRect[3] - 15)
HighPolyModelMenu = Draw.Menu (objectMeshMenuName, BUTTON_EVENT_SELECTED_HPMODELMENU, \
remainRect[0], remainRect[3] - 20, 140, 20, \
HighPolyModelMenu.val, "High Poly Object selected for Normal map")
Draw.Button ("Export NMF", BUTTON_EVENT_EXPORT_NMF, remainRect[0] + 150, remainRect[3] - 32, 80, 20, "export selected objects to ATI normal map format")
remainRect[3] -= 20
drawText (" Low Poly Mesh: ", 10, remainRect[3] - 15)
LowPolyModelMenu = Draw.Menu (objectMeshMenuName, BUTTON_EVENT_SELECTED_LPMODELMENU, \
remainRect[0], remainRect[3] - 20, 140, 20, \
LowPolyModelMenu.val, "Low Poly Object selected for Normal map")
remainRect[3] -= 30
remainRect[0] = 10
boxFilterToggle = Draw.Toggle ("Box Filter", BUTTON_EVENT_BOXFILTER, \
remainRect[0], remainRect[3] - 25, 60, 20, \
boxFilterToggle.val, "apply box filter post processing to normal map")
SamplePerTexelMenu = Draw.Menu ( \
"Samples per Texel %t|1 sample %x-1|5 samples %x1|10 samples %x2|70 samples %x3", \
BUTTON_EVENT_SAMPLEPERTEXEL, \
remainRect[0] + 70, remainRect[3] - 25, 90, 20, \
SamplePerTexelMenu.val, "number of samples per texel for Ray casting")
normalSpaceMenu = Draw.Menu ( \
"Normal %t|Tangent Space %x0|World Space %x1", \
BUTTON_EVENT_NORMALSPACE, \
remainRect[0] + 170, remainRect[3] - 25, 110, 20, \
normalSpaceMenu.val, "The space that the Normal Vector is in")
borderExpandMenu = Draw.Menu ( \
"Border Expansion %t|Border : None %x0|Border : 10 %x-1|Border : 15 %x1|Border : 20 %x2|Border : 30 %x3", \
BUTTON_EVENT_BORDEREXPAND, \
remainRect[0] + 290, remainRect[3] - 25, 110, 20, \
borderExpandMenu.val, "Border expansion in texels")
remainRect[3] -= 25
bumpMapToggle = Draw.Toggle ("Use Bump Map", BUTTON_EVENT_BUMPMAPTOGGLE, \
remainRect[0], remainRect[3] - 25, 90, 20, \
bumpMapToggle.val, "apply bump map to normal map")
if bumpMapToggle.val:
heightScaleNumber = Draw.Number ("Height Scale : ", BUTTON_EVENT_HEIGHTSCALENUMBER, \
remainRect[0] + 130, remainRect[3] - 25, 220, 20, \
heightScaleNumber.val, 0.0, 5.0, "scale factor")
remainRect[3] -= 20
BumpMapString = Draw.String ("Bump Map File: ", BUTTON_EVENT_BUMPSTRING, \
10, remainRect[3] - 25, guiRect[2] - 91, 20, \
BumpMapString.val, 255, "the bump map file to be applied to the normal map")
Draw.Button ("Select", BUTTON_EVENT_BUMPBUTTON, guiRect[2] - 80, remainRect[3] - 25, 70, 20, "select the bump map file to use")
remainRect[3] -= 50
remainRect[0] = drawText (" Normal Map Size: ", 10, remainRect[3] - 15)
TextureSizeMenu = Draw.Menu ("Size %t|64 %x64|128 %x128|256 %x256|512 %x512|1024 %x1024", BUTTON_EVENT_SELECTED_TEXTURESIZE, \
remainRect[0], remainRect[3] - 20, 60, 20, \
TextureSizeMenu.val, "Normal Map texture size")
remainRect[3] -= 25
Draw.Button ("Build Normal Map", BUTTON_EVENT_BUILD_NORMALMAP, remainRect[0] + 150, remainRect[3] - 20, 130, 45, "export selected objects and build normal map")
NormalMapNameString = Draw.String ("Normal Map File Name: ", BUTTON_EVENT_NORMALMAPSTRING, \
10, remainRect[3] - 20, 250, 20, \
NormalMapNameString.val, 50, "file name of output texture from Normal Mapper")
remainRect[3] -= 25
return
initGUI()
Draw.Register (gui, eventCallback, buttonCallback)
try to run this from text window, alt-p. and unwrap lines manually if need be. that said, this is unsupported version
edit: yes, some lines got wrapped. you’ll need to do some cleanup, but not too much.
I copy pasted it and alt-p and it still didnt work…
When is your build from,
there was a recent commit to python that seems to have made some previously working scripts no longer function.
So if it is a CVS build in the last 2 or 3 days, try an earlier build first.
LetterRip
Its not a CVS build its just blender 2.36 from the blender3d website. Maybe it will work in blender 2.37 which should come out soon.
themonkey: I have been using it with Blender 2.36 + Python 2.3.5 for about 3 months now with no problems. Could you post what comes up in the console window when you run the script and get the script error.
The installation instructions can be found here in the help section:
http://www.neuralfuzz.com/opengl/blender/normalmapping/Help
Error: Python script error: check console
ok, and what did it say in the console?