help to port to 2.6

here is a very old 2.49 script to make a sort of height map

and it is using the old nmesh command which does not exit in 2.6
so not certain how this could be ported to 2.6


import Blender
from Blender import *
from math import *
import PIL
from PIL import Image
 

pic = Image.open("c:/he1.jpg")


width = pic.size[0]
ht = pic.size[1]
me = NMesh.GetRaw()
df = list(pic.getdata())

for i in range (0,ht):

    for j in range (0,width):
    
        loc = j + (i*width)
        dy = df[loc]
        dz = dy[0]*.1 #grab first tuple
        v = NMesh.Vert(i,j,dz)
        me.verts.append(v)
        
        
for u in range (0,ht - 1):

   for w in range (0,width - 1):
   
      f= NMesh.Face()
      f.v.append (me.verts[u*width+w])
      f.v.append (me.verts[u*width+w+1])
      f.v.append (me.verts[(u+1)*width+w+1])
      f.v.append (me.verts[(u+1)*width+w])
      f.smooth = 1
      me.faces.append(f)
      
NMesh.PutRaw(me, "piltest", 1)
Blender.Redraw()

print (' ht=',ht)
print (' width=',width)
	
	


if it was posible to find a way to get teh path to the local folder
it would also help to make it more user friendly

another version using PIL might also make it run much faster!

any help appreciated
and might be usefull for other peoples too

thanks

if this creates a mesh from hightmap, why not use a displace modifier?

this is made to create a real 3D mesh
which is sort of a displacement mesh and not a texture!
so it is something interesting

and there is someone else who wants this also!
hope he can add his comments too soon

i assune here that image is not part of PIL
and it is working in 2.49

on 2.6 i don’t have PIL and it is working in another script

i could begin something with Bmesh
but might not be very elegant!

thanks

If I understand your script, you’re creating a “planar” mesh where each vertex matches a pixel of your image with its height modified according to the pixel value, is that right ? If it’s so, I agree with CoDEmanX, create a plane, subdivide it in order to get the correct number of vertices and put a displace modifier. If you apply the modifier, you’ll have a real 3D mesh at your disposal. Of course, a direct script like yours will probably be quicker, but it is the idea, correct ?

For the questions about PIL and the access to the local folder, I can’t help, sorry.

EDIT : Oops, didn’t see batFINGER post.

Following script runs on Blender 2.69, written based on @RickyBlender’s original snippet.
Some bugs will be fixed later


import bpy
import math
import mathutils
from mathutils import Vector, Matrix
realpath_pic = "c:/he1-test.jpg"
try:
        pic = bpy.data.images.load(realpath_pic)
except:
    raise NameError("Cannot load image %s" % realpath_pic)
width = pic.size[0]
ht = pic.size[1]
me = bpy.data.meshes.new(name='piltest')
df = pic.pixels
length = len(df)
pixel_len = 4
vs = []
for i in range (0,ht):
    for j in range (0,width):
         loc = j + (i*width) * pixel_len
         dy = []
         dy.append(df[loc])
         dz = (dy[0])  #grab first tuple
         v = (i,j,dz)
         vs.append(v)
         fs = []        
for u in range (0,ht - 1):
    for w in range (0,width - 1):
              v1 = u*width+w
              v2 = u*width+w+1
              v3 = (u+1)*width+w+1
              v4 = (u+1)*width+w
              #f.smooth = 1   #?
              fs.append((v1, v2, v3, v4))
            
me.from_pydata(vs, [], fs)
# Update mesh with new data
me.update(calc_edges=True)
ob = bpy.data.objects.new('ob1', me)
print (' ht=',ht)
print (' width=',width)

well this is not to make a height map but thanks for the links

this really makes a displacement mesh from a BW real photo pic
see example here


the first pass in to this snippet gives a very hight res model
easy to get inot millions of verts
so need to decimate or remesh or may be retopo it it get a lower res model!

this is ore like making a bas relief i think
and you cannot really look at it from large angles too!

i’ try to make a first script later this week and see if it can begin to work
using Bmesh

thanks

began a small panel here and added this class to select a file in current folder
but i cannot get the file name ?

can someone help make this work
and what is the function of the invoke here
when you click on the button for path is it going to do the execute or the invoke part ?



##
      
class OBJECT_OT_CustomPath(bpy.types.Operator):
    
    global p
    bl_idname = "object.custom_path"
    bl_label = "Custom Path"
    __doc__ = "OBJECT_OT_CustomPath"
    
    #this can be look into the one of the export or import python file.
    #settings
    #need to set a path so so we can get the file name and path
    
    path = p1.StringProperty(name="file path", description="getting file path", maxlen= 1024, default= "")
    
    def execute(self, context):
                                                            # set the string path for the file here.
                                                            # this is a variable created from the top to start it
        bpy.context.scene.custompath = self.properties.path
        print(self.properties.path)                        # display the file name and current path
    
    
    
    
        return {'FINISHED'}
    
    def invoke(self, context, event):
    
        print(self.properties.path)
    
    
        wm = bpy.context.window_manager  
        bpy.context.window_manager.fileselect_add(self)
    
        return {'RUNNING_MODAL'}
    
    
###
    

thanks

a direct script like yours will probably be quicker

I doubt that, 'cause the Displace modifier is C, whereas a script would be python (probably much slower!)

For the questions about PIL and the access to the local folder, I can’t help, sorry.

PIL is a Python 2.x library for fast image processing, there are Py 3k replacements like Pillow. Since no such library is shipped with blender, I would rather use Blender’s abilities (bpy.data.images.load, Image.pixels).

You’re completely misunderstanding the issue. I didn’t say anything about hightmap creation, but to create a mesh FROM a heightmap (which can be any image, not necessarily a grayscale bump map).

It’s not about bump or normal mapping either (also not parallax occlusion mapping and other techniques, that give an impression of depth, although there’s not). The Displacement modifier displaces the mesh verts in a non-destructive way, but the offsets will persist if applied.

the first pass in to this snippet gives a very hight res model
easy to get inot millions of verts
so need to decimate or remesh or may be retopo it it get a lower res model!

I disagree, you could use remove doubles or limited dissolve, or even better, prune superfluous pixels / interpolate them on mesh creation.

displacement modifier is sort of an equivalent i guess to this but not certain if it does the same algo
anyway would like to port it and then do some comparison
might be interesting if there is any differences!

i have a few model i did in 2.49 with this and i don’t remember it gave the same thing
this snippet seems to give better results but have to do more testing!

now what about this class for selecting a file which was working before but
not anymore due to some API changes again
i need to get the file name and may be the path alone!

i have some sculpted furnitures around and i’ll try to take good pcitures and do some testing
and see what it gives with displace modfiierand this snippet when it works in 2.6!

thanks

displacement modifier is sort of an equivalent i guess to this but not certain if it does the same algo

There’s not even an algorithm, only the characteristic, that every pixels maps to one vertex. If you create a grid mesh with one vertex for every pixel and as many vertices in a row as pixels in the image, displacement modifier will do exactly the same (but will let you do adjustments in realtime).

so this would be the same effect and not usefull to port it !

i’ll make another test with displacement modifier and see if it does about samething!

but still would like to see this old code snippet for path work again in 2.69 if possible might be usefull later on
mind you it was working a few months back but now don’t work!

class OBJECT_OT_CustomPath(bpy.types.Operator):

thanks

@RickyBlender, following script was written based on your snippet, it runs on Blender 2.69

import bpy
import math
import mathutils
from mathutils import Vector, Matrix
#realpath_pic = "c:/he1.jpg"
realpath_pic = "c:/bump-160x90.jpg"
try:
    pic = bpy.data.images.load(realpath_pic)
except:
    raise NameError("Cannot load image %s" % realpath_pic)
width = pic.size[0]
ht = pic.size[1]
me = bpy.data.meshes.new(name='piltest')
df = pic.pixels
pic_data_len = len(df)
pixel_len = int(pic_data_len / (width * ht))
print (' pixel_len=',pixel_len) 
vs = []
scale = 15
for i in range (0,ht):
    for j in range (0,width):
       loc = (j + (i*width)) * pixel_len
       dy = []
       dy.append(df[loc])
       dz = (dy[0]) #grab first tuple
       dz = dz * scale
       v = (i,j,dz)
       vs.append(v)
fs = [] 
for u in range (0,ht - 1):
    for w in range (0,width - 1):
        v1 = u*width+w
        v2 = u*width+w+1
        v3 = (u+1)*width+w+1
        v4 = (u+1)*width+w
        #f.smooth = 1 #?
        fs.append((v1, v2, v3, v4))
ob = bpy.data.objects.new('ob1', me)
ob.location = (0,0,0)
ob.show_name = True
# Link object to scene
bpy.context.scene.objects.link(ob)
me.from_pydata(vs, [], fs)
# Update mesh with new data
me.update(calc_edges=True)
print (' ht=',ht)
print (' width=',width) 
 

@grammer

for better results copy the pixel collection, also you have your order messed up giving a mirror image


df = img.pixels[:]

@RickyB
I’d still suggest creating a displacement (or normal map) instead of a mesh. Here is the result of grammer’s script on the left and the displacement modifier on the right, slapped onto a 10x10 (square) grid with subsurf 5. A grid with dimensions that match the image better and a crease on the edge would have yielded still better results.

Even if you are going to do some fancy edge detection fourier transforms etc… I’d create an image result rather than a mesh, then use displacement modifier on that result rather than a pixel w x h mesh, as CoDEmanX has pointed out.

Attachments


i ahve to find my old 2.59 build to make another test where i have the PIL
don’t know if there is a new PIL version right now for 2.5?

i know that PIL has the advantage to work way faster then Image thing
i did a test yesterday with image and one png file is working the other one is crashing
and cannot pin point why it cannot read other png file!

hope to get a new PC soon cause at 1E6 pixels it is crawling anyway!

you example look nice
to retopo taht do you need to apply it or retopo can see the subsurf ?

thanks

i will probably have to get new PIL cause it is like 1000 times faster

is there in blender something else then data.image to work with pixels?
cause even loading a 100 X 100 pixel takes few seconds
working with pixels is so sluggish i mean my PC is crawling !LOL

thanks

Load the image using bpy.data.images.load(), that should be pretty fast (max. 1 sec on decent computer with 4k*4k texture)

Then create a copy of Image.pixels like
px = img.pixels[:]

And use px, that should be quite fast too, and PIL won’t help much as the bottleneck is going to be the mesh creation from pixel info (that’s why you should use the Displace modifier).

See my post above about PIL, and check here:

@ Grammar

got a problem on window with relative path
i can give full path which is very long
or is there a way to acces the local blend file folder directly ?
tried with // but did not work !

thanks



>>> bpy.data.filepath
'F:\\blender\\BAFSamples\\away_away.blend'

there are rel and abs path methods in bpy.path

My suggestion would be to put a StringProperty(subtype=‘DIR_PATH’) on a prop and in a Panel, or just load the image and access it using bpy.data.images.get('Whatevername")… that’s what I did with bogey. Putting abs filepaths in code is a PITA.

ojst tried a direct access
realpath_pic = “image1.jpg” and it simply works !

rel or abs path seems to be more complicated and also depends on the command i think!

can somone tell me hwo to make the old path functions i’v shown to work again
woudl like to see this work in 2.69

i tested the new update script and it seems to work but it takes like 1 minute to get a new mesh!
as i said doing it directly with image is very slow

have to see how to make a copy in memory and how fast it can be done

thanks

For PIL is there an download install so i can install it on windows !
or which version should i get and install ?

thanks