UV/image projection

Hi all

Today i made a script (couldn’t find a script that does this job). It projects an image on to a mesh and renders the resulting texture.(atm only through xyz axis) It’s a bit like UVproject modifier, it looks the same, but works different. UVproject changes the UV coordinates, while this script keeps the uv but renders the image. Useful if you make an object from a photograph, and when unwrapped you can use the same photograph as texture. I made it, because painting on the texture makes distortions, straight lines don’t stay straight.

Problem… there’s no gui, and it works in a strange way… I found no way to draw directly to the texture, so i had to draw on blender(at every redraw :(), and “manually” copy it in the texture. Maybe somebody else made something similar? If not, is there anyone with some insights of blender who can help me to improve the script? Please don’t be mean, it’s the first time I use python.

If you want to try it. Just get a mesh, call it “uvproj”, unwrap it any way you like (doesn’t matter for the result, that’s the point ;)) Select the uv-faces, create an image in the UV/Image editor. (2^n width and same height) Hack in the script to change the image path(2^n width and same height) Atm it projects through the y axis. The image gets scaled to fit between the bounding square.

It works by changing x and z by u and v, and vice versa.

Please post any problems and/or improvements.

Cheers
Ishtar


import Blender
from Blender import Image,Draw,Window,Mesh,Mathutils
from Blender.BGL import *

CLEAR_R=0
CLEAR_G=0
CLEAR_B=0
CLEAR_A=0
TEXTURE_SIZE=Blender.Image.GetCurrent().getMaxXY()[0]

textureID = Image.Load("/home/ramon/image.png").glLoad()

def main():
	draw_texture()
	copyToTexture(Blender.Image.GetCurrent())

def draw_texture():
	global TEXTURE_SIZE,CLEAR_R,CLEAR_G,CLEAR_B,CLEAR_A,textureID
	glClearColor(CLEAR_R,CLEAR_G,CLEAR_B,CLEAR_A)
	glClear(GL_COLOR_BUFFER_BIT)
	glDisable(GL_DEPTH_TEST)
	glEnable(GL_TEXTURE_2D)
	glBindTexture(GL_TEXTURE_2D,textureID)
	glLoadIdentity()
	mesh=Mesh.Get('uvproj')
	if not mesh.faceUV:
		print "No faceUV"
		return
	minx=mesh.verts[0].co.x;
	maxx=mesh.verts[0].co.x;
	miny=mesh.verts[0].co.z;
	maxy=mesh.verts[0].co.z;
	for f in mesh.faces:
		for v in f.verts:
			if v.co.x < minx:
				minx=v.co.x
			if v.co.x > maxx:
				maxx=v.co.x
			if v.co.z < miny:
				miny=v.co.z
			if v.co.z > maxy:
				maxy=v.co.z
	
	glColor3f(1,1,1)
	glBegin(GL_TRIANGLES)
	for f in mesh.faces:
		if (len(f.verts)==3):
			for i in range(0,3):
				glTexCoord2d((f.verts[i].co.x-minx)*scx,(f.verts[i].co.z-miny)*scy);
				glVertex3f(TEXTURE_SIZE*f.uv[i].x-1,TEXTURE_SIZE*f.uv[i].y-1,0)
		else:
			#4 vertices, 2 tris.. I suppose this will work :)
			for i in range(0,3):
				glTexCoord2d((f.verts[i].co.x-minx)*scx,(f.verts[i].co.z-miny)*scy);
				glVertex3f(TEXTURE_SIZE*f.uv[i].x-1,TEXTURE_SIZE*f.uv[i].y-1,0)

			glTexCoord2d((f.verts[0].co.x-minx)*scx,(f.verts[0].co.z-miny)*scy);
			glVertex3f(TEXTURE_SIZE*f.uv[0].x-1,TEXTURE_SIZE*f.uv[0].y-1,0)
			
			glTexCoord2d((f.verts[2].co.x-minx)*scx,(f.verts[2].co.z-miny)*scy);
			glVertex3f(TEXTURE_SIZE*f.uv[2].x-1,TEXTURE_SIZE*f.uv[2].y-1,0)
			
			glTexCoord2d((f.verts[3].co.x-minx)*scx,(f.verts[3].co.z-miny)*scy);
			glVertex3f(TEXTURE_SIZE*f.uv[3].x-1,TEXTURE_SIZE*f.uv[3].y-1,0)
		
	glEnd()
			
def copyToTexture(image):
	global TEXTURE_SIZE
	pixels=Buffer(GL_BYTE,[TEXTURE_SIZE,TEXTURE_SIZE,4])
	viewport=Buffer(GL_INT,[1,4])
	glGetIntegerv(GL_VIEWPORT,viewport)
	mylist=viewport.list[0]
	glReadPixels(mylist[0],mylist[1],TEXTURE_SIZE,TEXTURE_SIZE,GL_RGBA,GL_UNSIGNED_BYTE,pixels)
	for i in range(0,TEXTURE_SIZE):
		for j in range(0,TEXTURE_SIZE):
			image.setPixelI(j,i,pixels[i][j])	

def ev(evt,val):
	Draw.Redraw(1)

Draw.Register(main,ev,None)
Draw.Redraw(1)