Best way to get Blender objects to OpenGL/C++

Compiling, libraries, modules, coding guidelines and porting

Moderators: jesterKing, stiv

Post Reply
cbranje
Posts: 0
Joined: Mon Apr 11, 2005 6:12 pm

Best way to get Blender objects to OpenGL/C++

Post by cbranje » Mon Apr 11, 2005 6:13 pm

What's the easiest/best way to take models from blender and "export" them so I can use them in C++ OpenGL code, so that I can create a walk through.

Thanks
Carmen

kakapo
Posts: 0
Joined: Sat Sep 04, 2004 2:32 pm

Post by kakapo » Mon Apr 11, 2005 6:20 pm

export as obj and read it in your application. obj is quite easy to understand and parse.

or use blender python to write an exporter for a custom format (or hardcoded opengl calls). you could just modify one of the existing python exporters.

SirDude
Posts: 233
Joined: Sun Oct 13, 2002 7:37 pm
Location: University of Minnesota (USA)
Contact:

Post by SirDude » Tue Apr 12, 2005 2:24 pm

There is also this openGL exporter:
http://www.geocities.com/dway_designer/ ... ter1.0.htm

mjordan
Posts: 0
Joined: Tue Nov 23, 2004 3:33 pm

Post by mjordan » Mon Apr 18, 2005 1:11 pm

Why not an OpenGL exporter in Bleder?
I find quite ridicolous an OpenGL app has a DirectX exporter and not an OpenGL one ...
:lol:
Regards,
Renato Perini
-
You can't live with women, you can't live without women.
Fuzzy logic example.

z3r0_d
Posts: 289
Joined: Wed Oct 16, 2002 2:38 am
Contact:

Post by z3r0_d » Mon Apr 18, 2005 5:31 pm

mjordan wrote:Why not an OpenGL exporter in Bleder?
I find quite ridicolous an OpenGL app has a DirectX exporter and not an OpenGL one ...
:lol:
opengl has a native format?

there is an opengl call to load a model in a standard well documented format?!?!

yeah, I didn't think so. someone could write an exporter which generated the code to render the model [what about loading the textures?], but interactive mode is slow... so then someone would want the exported code to render the model using a vertex buffer [still, what about loading the textures?]... and, how do we load a different model at runtime? So then say someone writes an exporter/importer combo... then essentially haven't they written the most primal parts of a graphics engine? what if someone wants skeletal animation? what if someone wants glsl? ...

why not just use ogre and their importer/exporter?

mjordan
Posts: 0
Joined: Tue Nov 23, 2004 3:33 pm

Post by mjordan » Mon Apr 18, 2005 5:55 pm

z3r0_d wrote:
mjordan wrote:Why not an OpenGL exporter in Bleder?
I find quite ridicolous an OpenGL app has a DirectX exporter and not an OpenGL one ...
:lol:
opengl has a native format?

there is an opengl call to load a model in a standard well documented format?!?!

yeah, I didn't think so. someone could write an exporter which generated the code to render the model [what about loading the textures?], but interactive mode is slow... so then someone would want the exported code to render the model using a vertex buffer [still, what about loading the textures?]... and, how do we load a different model at runtime? So then say someone writes an exporter/importer combo... then essentially haven't they written the most primal parts of a graphics engine? what if someone wants skeletal animation? what if someone wants glsl? ...

why not just use ogre and their importer/exporter?
No need to bother. I was just asking something like BOGLE (Blender OpenGL Exporter) directly integrated into Blender, for the simple reason this kind of scripts become obsolete very soon.
Loading different models at runtime is an app job, not a Blender job. I'm asking for a script that dumps the model's coordinates into an array, not a development environment.
Regards,
Renato Perini
-
You can't live with women, you can't live without women.
Fuzzy logic example.

z3r0_d
Posts: 289
Joined: Wed Oct 16, 2002 2:38 am
Contact:

Post by z3r0_d » Tue Apr 19, 2005 3:29 am

mjordan wrote:Loading different models at runtime is an app job, not a Blender job. I'm asking for a script that dumps the model's coordinates into an array, not a development environment.
simple export, public domain

Code: Select all

import struct
import Blender

def save(filename):
	objs = Blender.Object.GetSelected()
	if not len(objs) and objs[0].getType() == "mesh":
		Blender.Draw.PupMenu("active object must be a mesh")
		return
	obj = objs[0]
	mesh = obj.getData()
	
	f = open(filename, "wb")
	
	f.write(struct.pack("i",len(mesh.verts))) # vert count, as int
	
	vertDict = {} # used to speed finding vertex indicies
	index = 0
	for vert in mesh.verts:
		f.write(
			struct.pack("6f", # write each vert floats for coord [xyz] and normal [xyz]
				vert.co[0],vert.co[1],vert.co[2],
				vert.no[0],vert.no[1],vert.no[2]
				))
		vertDict[vert] = index
		index += 1
	
	# I don't know how many faces there are
	# since I will export only triangles I will now count them
	
	numfaces = 0
	for face in mesh.faces:
		if len(face.v) == 4:
			numfaces += 2
		elif len(face.v) == 3:
			numfaces += 1
			
	
	f.write(struct.pack("i",numfaces)) # vert count, as int
	
	# here I actually export the faces
	# a face is written as for each vert: int index to each vert, followed by two floats (uv)
	for face in mesh.faces:
		if len(face.v) == 4:
			# write face for 0 1 2, and face for 0 2 3
			f.write(struct.pack("iff iff iff",
				vertDict[face.v[0]], face.uv[0][0], face.uv[0][1],
				vertDict[face.v[1]], face.uv[1][0], face.uv[1][1],
				vertDict[face.v[2]], face.uv[2][0], face.uv[2][1]))
			f.write(struct.pack("iff iff iff",
				vertDict[face.v[0]], face.uv[0][0], face.uv[0][1],
				vertDict[face.v[2]], face.uv[2][0], face.uv[2][1],
				vertDict[face.v[3]], face.uv[3][0], face.uv[3][1]))
		elif len(face.v) == 3:
			f.write(struct.pack("iff iff iff",
				vertDict[face.v[0]], face.uv[0][0], face.uv[0][1],
				vertDict[face.v[1]], face.uv[1][0], face.uv[1][1],
				vertDict[face.v[2]], face.uv[2][0], face.uv[2][1]))
	
	f.close()
	print "### SIMPLE EXPORT COMPLETE ###"

Blender.Window.FileSelector(save, "Simple Export")
#save("E:\\Blender\\temp\\simple.exp")
simple import, public domain

Code: Select all

import struct
import Blender

def load(filename):
	f = open(filename, "rb")
	
	mesh = Blender.NMesh.New()
	
	numverts = struct.unpack("i",f.read(struct.calcsize("i")))[0] # vert count, as int
	
	print "%d verts"%numverts
	
	i = 0
	while i < numverts:
		i += 1
		vert = struct.unpack("6f",f.read(struct.calcsize("6f")))
		newvert = Blender.NMesh.Vert(*vert[:3])
		#newvert.no = list(vert[3:]) ## gets an error I'm too lazy to debug
		mesh.verts.append(newvert)
	
	numfaces = struct.unpack("i",f.read(struct.calcsize("i")))[0] # face count, as int
	
	print "%d faces"%numfaces
	
	i = 0
	while i < numfaces:
		i += 1
		face = struct.unpack("iff iff iff",f.read(struct.calcsize("iff iff iff")))
		newface = Blender.NMesh.Face(
			[mesh.verts[face[0]],mesh.verts[face[3]],mesh.verts[face[6]]])
		newface.uv = [
			(face[1],face[2]),(face[4],face[5]),(face[7],face[8]) ]
		mesh.faces.append(newface)
	
	mesh.update()
	# perhaps revise this to not have blender recalculate normals
	Blender.NMesh.PutRaw(mesh)
	f.close()
	print "### SIMPLE IMPORT COMPLETE ###"

Blender.Window.FileSelector(load, "Simple Import")
#load("E:\\Blender\\temp\\simple.exp")
I wrote these just now, they're incredibly simple and might be adequate. If nothing else they should give you some idea what to do to write your own exporter for meshes

mjordan
Posts: 0
Joined: Tue Nov 23, 2004 3:33 pm

Post by mjordan » Tue Apr 19, 2005 10:10 am

z3r0_d wrote:
mjordan wrote:Loading different models at runtime is an app job, not a Blender job. I'm asking for a script that dumps the model's coordinates into an array, not a development environment.
simple export, public domain

Code: Select all

import struct
import Blender

def save(filename):
	objs = Blender.Object.GetSelected()
	if not len(objs) and objs[0].getType() == "mesh":
		Blender.Draw.PupMenu("active object must be a mesh")
		return
	obj = objs[0]
	mesh = obj.getData()
	
	f = open(filename, "wb")
	
	f.write(struct.pack("i",len(mesh.verts))) # vert count, as int
	
	vertDict = {} # used to speed finding vertex indicies
	index = 0
	for vert in mesh.verts:
		f.write(
			struct.pack("6f", # write each vert floats for coord [xyz] and normal [xyz]
				vert.co[0],vert.co[1],vert.co[2],
				vert.no[0],vert.no[1],vert.no[2]
				))
		vertDict[vert] = index
		index += 1
	
	# I don't know how many faces there are
	# since I will export only triangles I will now count them
	
	numfaces = 0
	for face in mesh.faces:
		if len(face.v) == 4:
			numfaces += 2
		elif len(face.v) == 3:
			numfaces += 1
			
	
	f.write(struct.pack("i",numfaces)) # vert count, as int
	
	# here I actually export the faces
	# a face is written as for each vert: int index to each vert, followed by two floats (uv)
	for face in mesh.faces:
		if len(face.v) == 4:
			# write face for 0 1 2, and face for 0 2 3
			f.write(struct.pack("iff iff iff",
				vertDict[face.v[0]], face.uv[0][0], face.uv[0][1],
				vertDict[face.v[1]], face.uv[1][0], face.uv[1][1],
				vertDict[face.v[2]], face.uv[2][0], face.uv[2][1]))
			f.write(struct.pack("iff iff iff",
				vertDict[face.v[0]], face.uv[0][0], face.uv[0][1],
				vertDict[face.v[2]], face.uv[2][0], face.uv[2][1],
				vertDict[face.v[3]], face.uv[3][0], face.uv[3][1]))
		elif len(face.v) == 3:
			f.write(struct.pack("iff iff iff",
				vertDict[face.v[0]], face.uv[0][0], face.uv[0][1],
				vertDict[face.v[1]], face.uv[1][0], face.uv[1][1],
				vertDict[face.v[2]], face.uv[2][0], face.uv[2][1]))
	
	f.close()
	print "### SIMPLE EXPORT COMPLETE ###"

Blender.Window.FileSelector(save, "Simple Export")
#save("E:\\Blender\\temp\\simple.exp")
simple import, public domain

Code: Select all

import struct
import Blender

def load(filename):
	f = open(filename, "rb")
	
	mesh = Blender.NMesh.New()
	
	numverts = struct.unpack("i",f.read(struct.calcsize("i")))[0] # vert count, as int
	
	print "%d verts"%numverts
	
	i = 0
	while i < numverts:
		i += 1
		vert = struct.unpack("6f",f.read(struct.calcsize("6f")))
		newvert = Blender.NMesh.Vert(*vert[:3])
		#newvert.no = list(vert[3:]) ## gets an error I'm too lazy to debug
		mesh.verts.append(newvert)
	
	numfaces = struct.unpack("i",f.read(struct.calcsize("i")))[0] # face count, as int
	
	print "%d faces"%numfaces
	
	i = 0
	while i < numfaces:
		i += 1
		face = struct.unpack("iff iff iff",f.read(struct.calcsize("iff iff iff")))
		newface = Blender.NMesh.Face(
			[mesh.verts[face[0]],mesh.verts[face[3]],mesh.verts[face[6]]])
		newface.uv = [
			(face[1],face[2]),(face[4],face[5]),(face[7],face[8]) ]
		mesh.faces.append(newface)
	
	mesh.update()
	# perhaps revise this to not have blender recalculate normals
	Blender.NMesh.PutRaw(mesh)
	f.close()
	print "### SIMPLE IMPORT COMPLETE ###"

Blender.Window.FileSelector(load, "Simple Import")
#load("E:\\Blender\\temp\\simple.exp")
I wrote these just now, they're incredibly simple and might be adequate. If nothing else they should give you some idea what to do to write your own exporter for meshes
Shouldn't be good to have this nicely integrated into Blender? I think this scripts could be very handy sometimes. Expecially if they are well maintained along with Blender releases (read changes, here).

Code: Select all

#!BPY

"""
Name: 'BOGLE (Blender/OpenGL exporter)'
Blender: 232
Group: 'Misc'
Tooltip: 'Exportador de objetos a codigo C usando openGL'
"""

# By: cNavarro <irc://cralost@irc.cl><carlos.ns NOSPAM_IN g_m_a_i_l DOT c_o_m>
#
#Este fichero esta basada en una utilidad para la libreria TDLIB.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
#

import Blender
from Blender import Draw, BGL
from Blender import Types, Object, NMesh, Camera, Lamp
import sys

MESHEXP_RAWTRIANGLE = 0
MESHEXP_DOEXPORT= 0
MESHEXP_EXPFILE=""
ACCION_EXPORT = 1
ACCION_EXPORTARMESH=1
ACCION_EXPORTARESC=0
OBJETO_SELECCIONADO=""

CONF_MESHPATH=""

def __MSG(MSG):
 print MSG
 Blender.Draw.PupMenu("%s" % MSG)

def DefinirEXPFILE(valor):
 global MESHEXP_EXPFILE
 MESHEXP_EXPFILE=valor

def __EsValido(nobjeto):
 OBJETO_REF=0
 if len(nobjeto)!=0:
  OBJETO_REF = nobjeto[0].name
         if OBJETO_REF!="":
   return 1
  else:
   return 0

def __GetTipo(nobjeto):
 if __EsValido(nobjeto):
  return nobjeto[0].getType()

def __ExportarMesh(nfichero, nmesh):
 global MESHEXP_EXPFILE
 CONTA=0
 if (__GetTipo(nmesh)!="Mesh" or len(MESHEXP_EXPFILE)<1):
  if(__GetTipo(nmesh)!="Mesh"):
   __MSG("Error: Solo objetos tipo Mesh soportados")
  if(len(MESHEXP_EXPFILE)<1):
   __MSG("Error: No hay nombre de fichero")
 else:
  mshobj = Blender.NMesh.GetRaw(nmesh[0].data.name)
  faces = mshobj.faces
  vertices = mshobj.verts
  fichero = open(MESHEXP_EXPFILE, "wb")
  stdout_pipe=sys.stdout
  sys.stdout=fichero
  print "/*"
  print "Este fichero fue generado con BOGLE"
  print "*/"
  print "#include <GL/gl.h>"
  print ""
  print "void _BL_draw%s(int OPT)" % nmesh[0].data.name
  print "//nombre mesh: %s" % nmesh[0].data.name
  print "{"
  for fcount in mshobj.faces:
   CONTA=CONTA+1
   if fcount.smooth:
    print("\tglShadeModel(GL_SMOOTH);")
   else:
    print("\tglShadeModel(GL_FLAT);")

   if len(fcount.v) ==3:
    print "\tglBegin(GL_TRIANGLES);"
    print "\tglNormal3f(%f, %f, %f);" % (fcount.v[0].no.x ,fcount.v[0].no.z ,fcount.v[0].no.y)
    print "\tglVertex3f( %f, %f, %f);" % (fcount.v[0].co.x , fcount.v[0].co.z , fcount.v[0].co.y)
    print "\tglNormal3f(%f, %f, %f);" % (fcount.v[1].no.x ,fcount.v[1].no.z ,fcount.v[1].no.y)
    print "\tglVertex3f( %f, %f, %f);" % (fcount.v[1].co.x , fcount.v[1].co.z , fcount.v[1].co.y)
    print "\tglNormal3f(%f, %f, %f);" % (fcount.v[2].no.x ,fcount.v[2].no.z ,fcount.v[2].no.y)
    print "\tglVertex3f( %f, %f, %f);" % (fcount.v[2].co.x , fcount.v[2].co.z , fcount.v[2].co.y)
    print "\tglEnd();"

   if len(fcount.v) ==4:
    print "\tglBegin(GL_QUADS);"
    print "\tglNormal3f(%f, %f, %f);" % (fcount.v[0].no.x ,fcount.v[0].no.z ,fcount.v[0].no.y)
    print "\tglVertex3f( %f, %f, %f);" % (fcount.v[0].co.x , fcount.v[0].co.z , fcount.v[0].co.y)
    print "\tglNormal3f(%f, %f, %f);" % (fcount.v[1].no.x ,fcount.v[1].no.z ,fcount.v[1].no.y)
    print "\tglVertex3f( %f, %f, %f);" % (fcount.v[1].co.x , fcount.v[1].co.z , fcount.v[1].co.y)
    print "\tglNormal3f(%f, %f, %f);" % (fcount.v[2].no.x ,fcount.v[2].no.z ,fcount.v[2].no.y)
    print "\tglVertex3f( %f, %f, %f);" % (fcount.v[2].co.x , fcount.v[2].co.z , fcount.v[2].co.y)
    print "\tglNormal3f(%f, %f, %f);" % (fcount.v[3].no.x ,fcount.v[3].no.z ,fcount.v[3].no.y)
    print "\tglVertex3f( %f, %f, %f);" % (fcount.v[3].co.x , fcount.v[3].co.z , fcount.v[3].co.y)
    print "\tglEnd();"
  print "}"
  sys.stdout=stdout_pipe
  fichero.close() 
  __MSG("Mesh exportado con exito!")

def ExisteText(nfichero):
 retval = 0
 iii = 0
 ContenedoresTextos = Blender.Text.Get()
 nTextos = len(ContenedoresTextos)
 while iii< nTextos:
  if ContenedoresTextos[iii]==nfichero:
   retval = 1
  iii = iii+1
 return retval

def GetConf(nombreconf):
 retval = ""
 if ExisteText("% s.conf" % nombreconf):
  FicheroConf = Blender.Text.Get("% s.conf" % nombreconf)
  if FicheroConf:
   if FicheroConf.getNLines()==1:
    valorconf = FicheroConf.asLines()
    retval = valorconf[0]
 return retval

def HandleAccion():
 global ACCION_EXPORT, ACCION_EXPORTARMESH, ACCION_EXPORTAESC
 if ACCION_EXPORT == 1:
  ACCION_EXPORTARMESH=1
 else:
  ACCION_EXPORTARMESH=0
 if ACCION_EXPORT == 2:
  ACCION_EXPORTARESC=1
 else:
  ACCION_EXPORTARARM=0
 if ACCION_EXPORT == 3:
  ACCION_EXPORTARPOSE=1
 else:
  ACCION_EXPORTARPOSE=0


def DibujarGUI():
 global MESHEXP_RAWTRIANGLE
 global ACCION_EXPORT, ACCION_EXPORTARMESH, ACCION_EXPORTARARM, ACCION_EXPORTARPOSE
 global OBJETO_SELECCIONADO
 TipoDeObjeto = ""
 BGL.glClearColor(0.2,0.3,0.2,1)
 BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
 BGL.glColor3f(1,1,1)
 BGL.glRasterPos2i(20, 250)
 Draw.Text("BOGLE v0.1(Blender/OpenGL Exporter)")
 BGL.glColor3f(0,.2,0)
 BGL.glRasterPos2i(20, 240)
 Draw.Text("Este script es parte de el proyecto tdlib", "small")
 BGL.glColor3f(1,1,1)
 Draw.Toggle("Exportar Mesh",     11, 110, 5, 130, 20, ACCION_EXPORTARMESH,"Exportacion de mallas para uso con tdlib")
 Draw.Toggle("Exportar Escena", 12, 240, 5, 130, 20, ACCION_EXPORTARESC,"Exportacion de armatures para aplicacion de esqueletos")
 
 Draw.Button("Salir", 99, 5, 5, 100, 20,"Haz click aqui para salir")
 if ACCION_EXPORT==1:
  Draw.Button("Exportar a codigo C/C++", 14, 320, 50, 170, 50, "Haga click aqui para realizar la exportacion")
  ObjetoSeleccionado = Blender.Object.GetSelected()
  if __EsValido(ObjetoSeleccionado):
   OBJETO_SELECCIONADO = ObjetoSeleccionado[0].getName()
  else:
   OBJETO_SELECCIONADO = "[NINGUNO]"
  if __GetTipo(ObjetoSeleccionado)=="Mesh":
   BGL.glColor3f(1,1,1)
  else:
   BGL.glColor3f(1,0,0)
  BGL.glRasterPos2i(20, 180)
  Draw.Text("Objeto Seleccionado '% s'" % OBJETO_SELECCIONADO)
  BGL.glRasterPos2i(120, 155)
  Draw.Text("Fichero: '%s'" % MESHEXP_EXPFILE)
  Draw.Button("examinar>>", 16, 20, 150, 90, 20, "Haga click aqui para realizar la exportacion")
  

def EventosGUI(evento, valor):
 global ARM_CONSERVAR_NAMES
 global OBJETO_SELECCIONADO
 ObjetoSeleccionado2 = Blender.Object.GetSelected()
 if ObjetoSeleccionado2:
  if OBJETO_SELECCIONADO!=ObjetoSeleccionado2[0].name:
   Draw.Redraw(1)

def EventosAPP(evento):
 global MESHEXP_RAWTRIANGLE
 global ACCION_EXPORT
 if evento==99:
  print "*>> Salida activada por usuario."
  Draw.Exit()
 if evento==10:
  if MESHEXP_RAWTRIANGLE:
   MESHEXP_RAWTRIANGLE=0
  else:
   MESHEXP_RAWTRIANGLE=1
  Draw.Redraw(1)
 if evento==14:
  __ExportarMesh("",Blender.Object.GetSelected())
 if evento==16:
  Blender.Window.FileSelector(DefinirEXPFILE, "Export Mesh") 
 if evento==11:
  ACCION_EXPORT = 1
  HandleAccion()
  Draw.Redraw(1)
 if evento==12:
  ACCION_EXPORT = 2
  HandleAccion()
  Draw.Redraw(1)

  
print GetConf("MESHPATH")
Draw.Register(DibujarGUI, EventosGUI, EventosAPP)
This is BOGLE, the script I was talking about. I have contacted the author to propose it to bf-blender developers for commit. Of course, committing this would means maintain it on a regular basis.
Regards,
Renato Perini
-
You can't live with women, you can't live without women.
Fuzzy logic example.

ch
Posts: 0
Joined: Sun Sep 19, 2004 9:42 am

Post by ch » Thu Apr 21, 2005 3:22 pm

if I run this script I get:

Code: Select all

IndentationError: expected an indented block
  File "blend2opengl.py.txt", line 46
    print MSG
        ^

is there a solution to fix it??
http://www.web-play-3d.de
German site with Blender Tutorials

krlost
Posts: 0
Joined: Mon Aug 14, 2006 2:47 am

Bogle new version (in english)

Post by krlost » Mon Aug 14, 2006 2:57 am

a new version of bogle tested in blender 2.42a

Download the zipped file from:
http://es.geocities.com/carlost_ns/bogle.zip
or visit:
http://stumbecker.blogspot.com/2006/07/ ... e-v01.html
Last edited by krlost on Sat Nov 03, 2007 3:37 pm, edited 2 times in total.

mjordan
Posts: 0
Joined: Tue Nov 23, 2004 3:33 pm

Re: Bogle new version (in english)

Post by mjordan » Mon Aug 14, 2006 2:01 pm

krlost wrote:a new version of bogle tested in blender 2.42a

Download the zipped file http://es.geocities.com/carlost_ns/camline.zip
or see http://stumbecker.blogspot.com/2006/07/ ... e-v01.html
Thank you.
Regards,
Renato Perini
-
You can't live with women, you can't live without women.
Fuzzy logic example.

Post Reply