diff --git a/source/shared_lib/include/graphics/model.h b/source/shared_lib/include/graphics/model.h index ca9efc36..08b93d1b 100644 --- a/source/shared_lib/include/graphics/model.h +++ b/source/shared_lib/include/graphics/model.h @@ -72,6 +72,7 @@ private: bool twoSided; bool customColor; bool noSelect; + bool glow; uint32 textureFlags; @@ -133,6 +134,7 @@ public: bool getTwoSided() const {return twoSided;} bool getCustomTexture() const {return customColor;} bool getNoSelect() const {return noSelect;} + bool getGlow() const {return glow;} string getName() const {return name;} uint32 getTextureFlags() const { return textureFlags; } diff --git a/source/shared_lib/include/graphics/model_header.h b/source/shared_lib/include/graphics/model_header.h index cf15addc..efe277a1 100644 --- a/source/shared_lib/include/graphics/model_header.h +++ b/source/shared_lib/include/graphics/model_header.h @@ -43,7 +43,8 @@ enum ModelType{ enum MeshPropertyFlag{ mpfCustomColor= 1, mpfTwoSided= 2, - mpfNoSelect= 4 + mpfNoSelect= 4, + mpfGlow= 8 }; enum MeshTexture{ diff --git a/source/shared_lib/sources/graphics/gl/model_renderer_gl.cpp b/source/shared_lib/sources/graphics/gl/model_renderer_gl.cpp index 41107f60..e1bf5224 100644 --- a/source/shared_lib/sources/graphics/gl/model_renderer_gl.cpp +++ b/source/shared_lib/sources/graphics/gl/model_renderer_gl.cpp @@ -175,6 +175,12 @@ void ModelRendererGl::renderMesh(Mesh *mesh,int renderMode) { glEnable(GL_CULL_FACE); } + if(renderMode==rmNormal && mesh->getGlow()==true){ + // glow on + glDisable(GL_LIGHTING); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + } + if(this->colorPickingMode == false) { //set color if(renderColors) { @@ -324,6 +330,12 @@ void ModelRendererGl::renderMesh(Mesh *mesh,int renderMode) { glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, mesh->getIndices()); } + // glow + if(renderMode==rmNormal && mesh->getGlow()==true){ + // glow off + glEnable(GL_LIGHTING); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } //assertions assertGl(); } diff --git a/source/shared_lib/sources/graphics/model.cpp b/source/shared_lib/sources/graphics/model.cpp index 57ff5fc3..d261e14d 100644 --- a/source/shared_lib/sources/graphics/model.cpp +++ b/source/shared_lib/sources/graphics/model.cpp @@ -225,6 +225,7 @@ Mesh::Mesh() { twoSided= false; customColor= false; noSelect= false; + glow= false; textureFlags=0; @@ -446,6 +447,7 @@ void Mesh::loadV2(int meshIndex, const string &dir, FILE *f, TextureManager *tex twoSided= false; customColor= false; noSelect= false; + glow= false; if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Load v2, this = %p Found meshHeader.hasTexture = %d, texName [%s] mtDiffuse = %d meshIndex = %d modelFile [%s]\n",this,meshHeader.hasTexture,toLower(reinterpret_cast(meshHeader.texName)).c_str(),mtDiffuse,meshIndex,modelFile.c_str()); @@ -586,6 +588,7 @@ void Mesh::loadV3(int meshIndex, const string &dir, FILE *f, twoSided= (meshHeader.properties & mp3TwoSided) != 0; customColor= (meshHeader.properties & mp3CustomColor) != 0; noSelect = false; + glow = false; textureFlags= 0; if((meshHeader.properties & mp3NoTexture) != mp3NoTexture) { @@ -781,6 +784,7 @@ void Mesh::load(int meshIndex, const string &dir, FILE *f, TextureManager *textu customColor= (meshHeader.properties & mpfCustomColor) != 0; twoSided= (meshHeader.properties & mpfTwoSided) != 0; noSelect= (meshHeader.properties & mpfNoSelect) != 0; + glow= (meshHeader.properties & mpfGlow) != 0; //material diffuseColor= Vec3f(meshHeader.diffuseColor); @@ -900,6 +904,9 @@ void Mesh::save(int meshIndex, const string &dir, FILE *f, TextureManager *textu if(noSelect) { meshHeader.properties |= mpfNoSelect; } + if(glow) { + meshHeader.properties |= mpfGlow; + } meshHeader.textures = textureFlags; fwrite(&meshHeader, sizeof(MeshHeader), 1, f); @@ -1532,6 +1539,7 @@ void Mesh::copyInto(Mesh *dest, bool ignoreInterpolationData, dest->twoSided = this->twoSided; dest->customColor = this->customColor; dest->noSelect = this->noSelect; + dest->glow = this->glow; dest->textureFlags = this->textureFlags; @@ -1605,6 +1613,7 @@ void Model::autoJoinMeshFrames() { string("_") + intToStr(mesh.getCustomTexture()) + string("_") + intToStr(mesh.getNoSelect()) + string("_") + floatToStr(mesh.getOpacity()) + + string("_") + floatToStr(mesh.getGlow()) + string("_") + mesh.getDiffuseColor().getString() + string("_") + mesh.getSpecularColor().getString() + string("_") + floatToStr(mesh.getSpecularPower()); diff --git a/source/tools/glexemel/g3d_support.py b/source/tools/glexemel/g3d_support.py index 943a9f66..db15670c 100644 --- a/source/tools/glexemel/g3d_support.py +++ b/source/tools/glexemel/g3d_support.py @@ -1,507 +1,929 @@ -#!BPY -""" -Name: 'G3D Fileformat Im/Exporter' -Blender: 237 -Group: 'Wizards' -Tooltip: 'Imports and Exports the Glest fileformat V3/V4 (.g3d)' -""" +# -*- coding: utf-8 -*- + ########################################################################### # Glest Model / Texture / UV / Animation Importer and Exporter # for the Game Glest that u can find http://www.glest.org # copyright 2005 By Andreas Becker (seltsamuel@yahoo.de) # -# Updated Jan 2011 by Mark Vejvoda (SoftCoder) to properly import animations -# from G3D into Blender +# 2011/05/25: v0.1 alpha1 +# modified by William Zheng for Blender 2.57(loveheaven_zhengwei@hotmail.com) # -# Started Date: 07 June 2005 Put Public 20 June 2005 -# Ver: 0.01 Beta Exporter ripped off because work in Progress -# Distributed under the GNU PUBLIC LICENSE for www.megaglest.org and glest.org +# corrected by MrPostiga for Blender 2.58 +# +# extended by Yggdrasil +# +# Started Date: 07 June 2005 Put Public 20 June 2005 +# Distributed under the GNU PUBLIC LICENSE +#""" +#Here an explanation of the V4 Format found at www.glest.org +#================================ +#1. DATA TYPES +#================================ +#G3D files use the following data types: +#uint8: 8 bit unsigned integer +#uint16: 16 bit unsigned integer +#uint32: 32 bit unsigned integer +#float32: 32 bit floating point +#================================ +#2. OVERALL STRUCTURE +#================================ +#- File header +#- Model header +#- Mesh header +#- Texture names +#- Mesh data +#================================ +#2. FILE HEADER +#================================ +#Code: +#struct FileHeader{ +# uint8 id[3]; +# uint8 version; +#}; +#This header is shared among all the versions of G3D, it identifies this file as a G3D model and provides information of the version. +#id: must be "G3D" +#version: must be 4, in binary (not '4') +#================================ +#3. MODEL HEADER +#================================ +#Code: +#struct ModelHeader{ +# uint16 meshCount; +# uint8 type; +#}; +#meshCount: number of meshes in this model +#type: must be 0 +#================================ +#4. MESH HEADER +#================================ +#There is a mesh header for each mesh, there must be "meshCount" headers in a file but they are not consecutive, texture names and mesh data are stored in between. +#Code: +#struct MeshHeader{ +# uint8 name[64]; +# uint32 frameCount; +# uint32 vertexCount; +# uint32 indexCount; +# float32 diffuseColor[3]; +# float32 specularColor[3]; +# float32 specularPower; +# float32 opacity; +# uint32 properties; +# uint32 textures; +#}; +#name: name of the mesh +#frameCount: number of keyframes in this mesh +#vertexCount: number of vertices in each frame +#indexCount: number of indices in this mesh (the number of triangles is indexCount/3) +#diffuseColor: RGB diffuse color +#specularColor: RGB specular color (currently unused) +#specularPower: specular power (currently unused) +##properties: property flags +#Code: +#enum MeshPropertyFlag{ +# mpfCustomColor= 1, +# mpfTwoSided= 2, +# mpfNoSelect= 4 +#}; +#mpfTwoSided: meshes in this mesh are rendered by both sides, if this flag is not present only "counter clockwise" faces are rendered +#mpfCustomColor: alpha in this model is replaced by a custom color, usually the player color +#textures: texture flags +#Code: +#enum MeshTexture{ +# diffuse = 1, +# specular = 2, +# normal = 4 +#}; +#================================ +#4. TEXTURE NAMES +#================================ +#A list of uint8[64] texture name values. One for each texture in the mesh. If there are no textures in the mesh no texture names are present. +#================================ +#5. MESH DATA +#================================ +#After each mesh header and texture names the mesh data is placed. +#vertices: frameCount * vertexCount * 3, float32 values representing the x, y, z vertex coords for all frames +#normals: frameCount * vertexCount * 3, float32 values representing the x, y, z normal coords for all frames +#texture coords: vertexCount * 2, float32 values representing the s, t tex coords for all frames (only present if the mesh has 1 texture at least) +#indices: indexCount, uint32 values representing the indices ########################################################################### -#NOTE: -# Copy this Script AND g3d_logo.png into .Blender\scripts -# directory then start inside blender Scripts window -# "Update Menus" after that this Script here is accesible -# as 'Wizards' G3d Fileformat Im/Exporter -#ToDo: -#Exporter Bughunt he will be rejoined next release -#Maybe Integrate UV Painter to Generate UVMaps from Blender Material and procedural Textures -#will be nice to paint wireframe too, so that one can easyly load into Paintprogram and see where to paint -#(Already possible through Blender functions so at the end of the list :-) ) -########################################################################### -""" -Here an explanation of the V4 Format found at www.glest.org -================================ -1. DATA TYPES -================================ -G3D files use the following data types: -uint8: 8 bit unsigned integer -uint16: 16 bit unsigned integer -uint32: 32 bit unsigned integer -float32: 32 bit floating point -================================ -2. OVERALL STRUCTURE -================================ -- File header -- Model header -- Mesh header -- Texture names -- Mesh data -================================ -2. FILE HEADER -================================ -Code: -struct FileHeader{ - uint8 id[3]; - uint8 version; -}; -This header is shared among all the versions of G3D, it identifies this file as a G3D model and provides information of the version. -id: must be "G3D" -version: must be 4, in binary (not '4') -================================ -3. MODEL HEADER -================================ -Code: -struct ModelHeader{ - uint16 meshCount; - uint8 type; -}; -meshCount: number of meshes in this model -type: must be 0 -================================ -4. MESH HEADER -================================ -There is a mesh header for each mesh, there must be "meshCount" headers in a file but they are not consecutive, texture names and mesh data are stored in between. -Code: -struct MeshHeader{ - uint8 name[64]; - uint32 frameCount; - uint32 vertexCount; - uint32 indexCount; - float32 diffuseColor[3]; - float32 specularColor[3]; - float32 specularPower; - float32 opacity; - uint32 properties; - uint32 textures; -}; -name: name of the mesh -frameCount: number of keyframes in this mesh -vertexCount: number of vertices in each frame -indexCount: number of indices in this mesh (the number of triangles is indexCount/3) -diffuseColor: RGB diffuse color -specularColor: RGB specular color (currently unused) -specularPower: specular power (currently unused) -properties: property flags -Code: -enum MeshPropertyFlag{ - mpfTwoSided= 1, - mpfCustomColor= 2, -}; -mpfTwoSided: meshes in this mesh are rendered by both sides, if this flag is not present only "counter clockwise" faces are rendered -mpfCustomColor: alpha in this model is replaced by a custom color, usually the player color -textures: texture flags, only 0x1 is currently used, indicating that there is a diffuse texture in this mesh. -================================ -4. TEXTURE NAMES -================================ -A list of uint8[64] texture name values. One for each texture in the mesh. If there are no textures in the mesh no texture names are present. In practice since Glest only uses 1 texture for each mesh the number of texture names should be 0 or 1. -================================ -5. MESH DATA -================================ -After each mesh header and texture names the mesh data is placed. -vertices: frameCount * vertexCount * 3, float32 values representing the x, y, z vertex coords for all frames -normals: frameCount * vertexCount * 3, float32 values representing the x, y, z normal coords for all frames -texture coords: vertexCount * 2, float32 values representing the s, t tex coords for all frames (only present if the mesh has 1 texture at least) -indices: indexCount, uint32 values representing the indices -""" + +bl_info = { + "name": "G3D Mesh Import/Export", + "description": "Import/Export .g3d file (Glest 3D)", + "author": "various, see head of script", + "version": (0, 11, 1), + "blender": (2, 65, 0), + "location": "File > Import-Export", + "warning": "always keep .blend files", + "wiki_url": "http://glest.wikia.com/wiki/G3D_support", + "tracker_url": "https://forum.megaglest.org/index.php?topic=6596", + "category": "Import-Export"} ########################################################################### # Importing Structures needed (must later verify if i need them really all) ########################################################################### -import Blender -from Blender import NMesh, Object, Scene -from Blender.BGL import * -from Blender.Draw import * -from Blender.Window import * -from Blender.Image import * +import bpy +from bpy.props import StringProperty +from bpy_extras.image_utils import load_image +from bpy_extras.io_utils import ImportHelper, ExportHelper +import bmesh + import sys, struct, string, types from types import * import os from os import path -from os.path import dirname +from os.path import dirname, abspath + +import subprocess +from mathutils import Matrix +from math import radians ########################################################################### # Variables that are better Global to handle ########################################################################### imported = [] #List of all imported Objects toexport = [] #List of Objects to export (actually only meshes) sceneID = None #Points to the active Blender Scene - +def unpack_list(list_of_tuples): + l = [] + for t in list_of_tuples: + l.extend(t) + return l ########################################################################### # Declaring Structures of G3D Format ########################################################################### -class G3DHeader: #Read first 4 Bytes of file should be G3D + Versionnumber - binary_format = "<3cB" - def __init__(self, fileID): - temp = fileID.read(struct.calcsize(self.binary_format)) - data = struct.unpack(self.binary_format,temp) - self.id = "".join(data[0:3]) - self.version = data[3] +class G3DHeader: #Read first 4 Bytes of file should be G3D + Versionnumber + binary_format = "<3cB" + def __init__(self, fileID): + temp = fileID.read(struct.calcsize(self.binary_format)) + data = struct.unpack(self.binary_format,temp) + self.id = str(data[0]+data[1]+data[2], "utf-8") + self.version = data[3] -class G3DModelHeaderv3: #Read Modelheader in V3 there is only the number of Meshes in file - binary_format = "> 3 + while tex: + tex &= tex - 1 # set rightmost 1-bit to 0 + # discard texture name, as we don't know what to do with it + fileID.seek(struct.calcsize(self.texname_format)) + print("warning: ignored texture in undefined texture slot") - # Make the keys animate in the 3d view. - key = mesh.key - key.relative = False +class G3DMeshdataV3: #Calculate and read the Mesh Datapack + def __init__(self,fileID,header): + #Calculation of the Meshdatasize to load because its variable + #Animationframes * Vertices per Animation * 3 (Each Point are 3 Float X Y Z Coordinates) + vertex_format = "<%if" % int(header.framecount * header.vertexcount * 3) + #The same for Normals + normals_format = "<%if" % int(header.normalframecount * header.vertexcount * 3) + #Same here but Textures are 2D so only 2 Floats needed for Position inside Texture Bitmap + texturecoords_format = "<%if" % int(header.texturecoordframecount * header.vertexcount * 2) + #Colors in format RGBA + colors_format = "<%if" % int(header.colorframecount * 4) + #Indices + indices_format = "<%iI" % int(header.indexcount) + #Load the Meshdata as calculated above + self.vertices = struct.unpack(vertex_format,fileID.read(struct.calcsize(vertex_format))) + self.normals = struct.unpack(normals_format,fileID.read(struct.calcsize(normals_format))) + self.texturecoords = struct.unpack(texturecoords_format,fileID.read(struct.calcsize(texturecoords_format))) + self.colors = struct.unpack(colors_format,fileID.read(struct.calcsize(colors_format))) + self.indices = struct.unpack(indices_format ,fileID.read(struct.calcsize(indices_format))) - # Add an IPO to teh Key - ipo = Blender.Ipo.New('Key', 'md2') - key.ipo = ipo - # Add a curve to the IPO - curve = ipo.addCurve('Basis') +class G3DMeshdataV4: #Calculate and read the Mesh Datapack + def __init__(self,fileID,header): + #Calculation of the Meshdatasize to load because its variable + #Animationframes * Points (Vertex) per Animation * 3 (Each Point are 3 Float X Y Z Coordinates) + vertex_format = "<%if" % int(header.framecount * header.vertexcount * 3) + #The same for Normals + normals_format = "<%if" % int(header.framecount * header.vertexcount * 3) + #Same here but Textures are 2D so only 2 Floats needed for Position inside Texture Bitmap + texturecoords_format = "<%if" % int(header.vertexcount * 2) + #Indices + indices_format = "<%iI" % int(header.indexcount) + #Load the Meshdata as calculated above + self.vertices = struct.unpack(vertex_format,fileID.read(struct.calcsize(vertex_format))) + self.normals = struct.unpack(normals_format,fileID.read(struct.calcsize(normals_format))) + if header.hastexture: + self.texturecoords = struct.unpack(texturecoords_format,fileID.read(struct.calcsize(texturecoords_format))) + self.indices = struct.unpack(indices_format ,fileID.read(struct.calcsize(indices_format))) - # Add 2 points to cycle through the frames. - curve.append((1, 0)) - curve.append((header.framecount, (header.framecount-1)/10.0)) - curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR +#Create a Mesh inside Blender +def createMesh(filename, header, data, toblender, operator): + mesh = bpy.data.meshes.new(header.meshname) #New Mesh + meshobj = bpy.data.objects.new(header.meshname+'Object', mesh) #New Object for the new Mesh + scene = bpy.context.scene + scene.objects.link(meshobj) + scene.update() + uvcoords = [] + img_diffuse = None + img_specular = None + img_normal = None + if header.hastexture: #Load Texture when assigned + try: + texturefile = dirname(abspath(filename)) + os.sep + header.diffusetexture + img_diffuse = bpy.data.images.load(texturefile) + for x in range(0,len(data.texturecoords),2): #Prepare the UV + uvcoords.append([data.texturecoords[x],data.texturecoords[x+1]]) + + if header.isv4: + if header.speculartexture: + texturefile = dirname(abspath(filename)) + os.sep + header.speculartexture + img_specular = bpy.data.images.load(texturefile) + if header.normaltexture: + texturefile = dirname(abspath(filename)) + os.sep + header.normaltexture + img_normal = bpy.data.images.load(texturefile) + except: + import traceback + traceback.print_exc() + + header.hastexture = False + operator.report({'WARNING'}, "Couldn't load texture. See console for details.") + + vertsCO = [] + vertsNormal = [] + for x in range(0,header.vertexcount*3,3): #Get the Vertices and Normals into empty Mesh + vertsCO.extend([(data.vertices[x],data.vertices[x+1],data.vertices[x+2])]) + vertsNormal.extend([(data.normals[x],data.normals[x+1],data.normals[x+2])]) + #vertsCO.extend([(data.vertices[x+(header.framecount-1)*header.vertexcount*3],data.vertices[x+(header.framecount-1)*header.vertexcount*3+1],data.vertices[x+(header.framecount-1)*header.vertexcount*3+2])]) + #vertsNormal.extend([(data.normals[x+(header.framecount-1)*header.vertexcount*3],data.normals[x+(header.framecount-1)*header.vertexcount*3+1],data.normals[x+(header.framecount-1)*header.vertexcount*3+2])]) + mesh.vertices.add(len(vertsCO)) + mesh.vertices.foreach_set("co", unpack_list(vertsCO)) + mesh.vertices.foreach_set("normal", unpack_list(vertsNormal)) + + faces = [] + faceuv = [] + for i in range(0,len(data.indices),3): #Build Faces into Mesh + faces.extend([data.indices[i], data.indices[i+1], data.indices[i+2], 0]) + if header.hastexture: + uv = [] + u0 = uvcoords[data.indices[i]][0] + v0 = uvcoords[data.indices[i]][1] + uv.append([u0,v0]) + u1 = uvcoords[data.indices[i+1]][0] + v1 = uvcoords[data.indices[i+1]][1] + uv.append([u1,v1]) + u2 = uvcoords[data.indices[i+2]][0] + v2 = uvcoords[data.indices[i+2]][1] + uv.append([u2,v2]) + faceuv.append([uv,0,0,0]) + else: + uv = [] + uv.append([0,0]) + uv.append([0,0]) + uv.append([0,0]) + faceuv.append([uv,0,0,0]) + mesh.tessfaces.add(len(faces)//4) + mesh.tessfaces.foreach_set("vertices_raw", faces) + mesh.tessfaces.foreach_set("use_smooth", [True] * len(mesh.tessfaces)) + mesh.g3d_customColor = header.customalpha + mesh.show_double_sided = header.istwosided + if header.isv4: + mesh.g3d_noSelect = header.noselect + mesh.g3d_glow = header.glow + else: + mesh.g3d_noSelect = False + mesh.glow = False + mesh.g3d_fullyOpaque = False + #=================================================================================================== + #Material Setup + #=================================================================================================== + def addtexslot(matdata,index,name,img): + texture = bpy.data.textures.new(name=name,type='IMAGE') + texture.image = img + slot = matdata.texture_slots.create(index) + slot.texture = texture + slot.texture_coords = 'UV' - return + if header.hastexture: + materialname = "pskmat" + materials = [] + matdata = bpy.data.materials.new(materialname + '1') + + addtexslot(matdata, 0, 'diffusetexture', img_diffuse) + if img_specular: + addtexslot(matdata, 1, 'speculartexture', img_specular) + if img_normal: + addtexslot(matdata, 2, 'normaltexture', img_normal) + + if header.isv4: + matdata.diffuse_color = (header.diffusecolor[0], header.diffusecolor[1],header.diffusecolor[2]) + matdata.alpha = header.opacity + matdata.specular_color = (header.specularcolor[0], header.specularcolor[1],header.specularcolor[2]) + materials.append(matdata) + + for material in materials: + #add material to the mesh list of materials + mesh.materials.append(material) + + countm = 0 + psktexname="psk" + str(countm) + mesh.tessface_uv_textures.new(name=psktexname) + if (len(faceuv) > 0): + for countm in range(len(mesh.tessface_uv_textures)): + uvtex = mesh.tessface_uv_textures[countm] #add one uv texture + for i, face in enumerate(mesh.tessfaces): + blender_tface = uvtex.data[i] #face + mfaceuv = faceuv[i] + if countm == faceuv[i][1]: + face.material_index = faceuv[i][1] + blender_tface.uv1 = mfaceuv[0][0] #uv = (0,0) + blender_tface.uv2 = mfaceuv[0][1] #uv = (0,0) + blender_tface.uv3 = mfaceuv[0][2] #uv = (0,0) + blender_tface.image = img_diffuse + else: + blender_tface.uv1 = [0,0] + blender_tface.uv2 = [0,0] + blender_tface.uv3 = [0,0] + imported.append(meshobj) #Add to Imported Objects + sk = meshobj.shape_key_add() + for x in range(1,header.framecount): #Put in Vertex Positions for Keyanimation + sk = meshobj.shape_key_add() + for i in range(0,header.vertexcount*3,3): + sk.data[i//3].co[0]= data.vertices[x*header.vertexcount*3 + i] + sk.data[i//3].co[1]= data.vertices[x*header.vertexcount*3 + i +1] + sk.data[i//3].co[2]= data.vertices[x*header.vertexcount*3 + i +2] + + # activate one shapekey per frame + for i in range(1,header.framecount): + shape = mesh.shape_keys.key_blocks[i] + shape.value = 0.0 + shape.keyframe_insert("value", frame=i) + shape.value = 1.0 + shape.keyframe_insert("value", frame=(i+1)) + shape.value = 0.0 + shape.keyframe_insert("value", frame=(i+2)) + + meshobj.active_shape_key_index = 0 + + if toblender: + # rotate from glest to blender orientation + #mesh.transform( Matrix( ((1,0,0,0),(0,0,-1,0),(0,1,0,0),(0,0,0,1)) ) ) + # doesn't work, maybe because of shape keys + # use object transformation instead + meshobj.rotation_euler = (radians(90), 0, 0) + + # update polygon structures from tessfaces + mesh.update() + mesh.update_tag() + + # remove duplicates + bm = bmesh.new() + bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.0001) + bm.to_mesh(mesh) + bm.free() + + return ########################################################################### # Import ########################################################################### -def G3DLoader(filename): #Main Import Routine - global imported, sceneID - print "\nNow Importing File : " + filename - fileID = open(filename,"rb") - header = G3DHeader(fileID) - print "\nHeader ID : " + header.id - print "Version : " + str(header.version) - if header.id != "G3D": - print "This is Not a G3D Model File" - fileID.close - return - if header.version not in (3, 4): - print "The Version of this G3D File is not Supported" - fileID.close - return - in_editmode = Blender.Window.EditMode() #Must leave Editmode when active - if in_editmode: Blender.Window.EditMode(0) - sceneID=Scene.getCurrent() #Get active Scene - scenecontext=sceneID.getRenderingContext() #To Access the Start/Endframe its so hidden i searched till i got angry :-) - basename=str(Blender.sys.makename(filename,"",1)) #Generate the Base Filename without Path + extension - imported = [] - maxframe=0 - if header.version == 3: - modelheader = G3DModelHeaderv3(fileID) - print "Number of Meshes : " + str(modelheader.meshcount) - for x in xrange(modelheader.meshcount): - meshheader = G3DMeshHeaderv3(fileID) - meshheader.isv4 = False - print "\nMesh Number : " + str(x+1) - print "framecount : " + str(meshheader.framecount) - print "normalframecount : " + str(meshheader.normalframecount) - print "texturecoordframecount: " + str(meshheader.texturecoordframecount) - print "colorframecount : " + str(meshheader.colorframecount) - print "pointcount : " + str(meshheader.vertexcount) - print "indexcount : " + str(meshheader.indexcount) - print "texturename : " + str(meshheader.texturefilename) - print "hastexture : " + str(meshheader.hastexture) - print "istwosided : " + str(meshheader.istwosided) - print "customalpha : " + str(meshheader.customalpha) - meshheader.meshname = basename+str(x+1) #Generate Meshname because V3 has none - if meshheader.framecount > maxframe: maxframe = meshheader.framecount #Evaluate the maximal animationsteps - meshdata = G3DMeshdataV3(fileID,meshheader) - createMesh(filename,meshheader,meshdata) - fileID.close - print "Imported Objects: ",imported - scenecontext.startFrame(1) #Yeah finally found this Options :-) - scenecontext.endFrame(maxframe) #Set it correctly to the last Animationstep :-)))) - Blender.Set("curframe",1) #Why the Heck are the above Options not here accessible ???? - anchor = Object.New("Empty",basename) #Build an "empty" to Parent all meshes to it for easy handling - sceneID.link(anchor) #Link it to current Scene - anchor.makeParent(imported) #Make it Parent for all imported Meshes - anchor.sel = 1 #Select it - if in_editmode: Blender.Window.EditMode(1) # Be nice and restore Editmode when was active - return - if header.version == 4: - modelheader = G3DModelHeaderv4(fileID) - print "Number of Meshes : " + str(modelheader.meshcount) - for x in xrange(modelheader.meshcount): - meshheader = G3DMeshHeaderv4(fileID) - meshheader.isv4 = False - print "\nMesh Number : " + str(x+1) - print "meshname : " + str(meshheader.meshname) - print "framecount : " + str(meshheader.framecount) - print "vertexcount : " + str(meshheader.vertexcount) - print "indexcount : " + str(meshheader.indexcount) - print "diffusecolor : %1.6f %1.6f %1.6f" %meshheader.diffusecolor - print "specularcolor : %1.6f %1.6f %1.6f" %meshheader.specularcolor - print "specularpower : %1.6f" %meshheader.specularpower - print "opacity : %1.6f" %meshheader.opacity - print "properties : " + str(meshheader.properties) - print "textures : " + str(meshheader.textures) - print "texturename : " + str(meshheader.texturefilename) - if len(meshheader.meshname) ==0: #When no Meshname in File Generate one - meshheader.meshname = basename+str(x+1) - if meshheader.framecount > maxframe: maxframe = meshheader.framecount #Evaluate the maximal animationsteps - meshdata = G3DMeshdataV4(fileID,meshheader) - createMesh(filename,meshheader,meshdata) - fileID.close - scenecontext.startFrame(1) #Yeah finally found this Options :-) - scenecontext.endFrame(maxframe) #Set it correctly to the last Animationstep :-)))) - Blender.Set("curframe",1) #Why the Heck are the above Options not here accessible ???? - anchor = Object.New("Empty",basename) #Build an "empty" to Parent all meshes to it for easy handling - sceneID.link(anchor) #Link it to current Scene - anchor.makeParent(imported) #Make it Parent for all imported Meshes - anchor.sel = 1 #Select it - if in_editmode: Blender.Window.EditMode(1) # Be nice and restore Editmode when was active - print "Created a empty Object as 'Grip' where all imported Objects are parented to" - print "To move the complete Meshes only select this empty Object and move it" - print "All Done, have a good Day :-)\n\n" - return -########################################################################### -# Export (Ripped out its work in Progress will be added soon -########################################################################### -def G3DSaverV3(filename): - return +def G3DLoader(filepath, toblender, operator): #Main Import Routine + global imported, sceneID + print ("\nNow Importing File: " + filepath) + fileID = open(filepath,"rb") + header = G3DHeader(fileID) + print ("\nHeader ID : " + header.id) + print ("Version : " + str(header.version)) + if header.id != "G3D": + print ("ERROR: This is Not a G3D Model File") + operator.report({'ERROR'}, "This is Not a G3D Model File") + fileID.close + return + if header.version not in (3, 4): + print ("ERROR: The Version of this G3D File is not Supported") + operator.report({'ERROR'}, "The Version of this G3D File is not Supported") + fileID.close + return + #in_editmode = Blender.Window.EditMode() #Must leave Editmode when active + #if in_editmode: Blender.Window.EditMode(0) + sceneID = bpy.context.scene #Get active Scene + #scenecontext=sceneID.getRenderingContext() #To Access the Start/Endframe its so hidden i searched till i got angry :-) + basename=os.path.basename(filepath).split('.')[0] #Generate the Base Filename without Path + extension + imported = [] + maxframe=0 + if header.version == 3: + modelheader = G3DModelHeaderv3(fileID) + print ("Number of Meshes : " + str(modelheader.meshcount)) + for x in range(modelheader.meshcount): + meshheader = G3DMeshHeaderv3(fileID) + meshheader.isv4 = False + print ("\nMesh Number : " + str(x+1)) + print ("framecount : " + str(meshheader.framecount)) + print ("normalframecount : " + str(meshheader.normalframecount)) + print ("texturecoordframecount: " + str(meshheader.texturecoordframecount)) + print ("colorframecount : " + str(meshheader.colorframecount)) + print ("pointcount : " + str(meshheader.vertexcount)) + print ("indexcount : " + str(meshheader.indexcount)) + print ("texturename : " + str(meshheader.diffusetexture)) + print ("hastexture : " + str(meshheader.hastexture)) + print ("istwosided : " + str(meshheader.istwosided)) + print ("customalpha : " + str(meshheader.customalpha)) + meshheader.meshname = basename+str(x+1) #Generate Meshname because V3 has none + if meshheader.framecount > maxframe: maxframe = meshheader.framecount #Evaluate the maximal animationsteps + meshdata = G3DMeshdataV3(fileID,meshheader) + createMesh(filepath, meshheader, meshdata, toblender, operator) + fileID.close + bpy.context.scene.frame_start=1 + bpy.context.scene.frame_end=maxframe + bpy.context.scene.frame_current=1 + anchor = bpy.data.objects.new('Empty', None) + anchor.select = True + bpy.context.scene.objects.link(anchor) + for ob in imported: + ob.parent = anchor + bpy.context.scene.update() + return + if header.version == 4: + modelheader = G3DModelHeaderv4(fileID) + print ("Number of Meshes : " + str(modelheader.meshcount)) + for x in range(modelheader.meshcount): + meshheader = G3DMeshHeaderv4(fileID) + meshheader.isv4 = True + print ("\nMesh Number : " + str(x+1)) + print ("meshname : " + str(meshheader.meshname)) + print ("framecount : " + str(meshheader.framecount)) + print ("vertexcount : " + str(meshheader.vertexcount)) + print ("indexcount : " + str(meshheader.indexcount)) + print ("diffusecolor : %1.6f %1.6f %1.6f" %meshheader.diffusecolor) + print ("specularcolor : %1.6f %1.6f %1.6f" %meshheader.specularcolor) + print ("specularpower : %1.6f" %meshheader.specularpower) + print ("opacity : %1.6f" %meshheader.opacity) + print ("properties : " + str(meshheader.properties)) + print ("textures : " + str(meshheader.textures)) + print ("texturename : " + str(meshheader.diffusetexture)) + if len(meshheader.meshname) ==0: #When no Meshname in File Generate one + meshheader.meshname = basename+str(x+1) + if meshheader.framecount > maxframe: maxframe = meshheader.framecount #Evaluate the maximal animationsteps + meshdata = G3DMeshdataV4(fileID,meshheader) + createMesh(filepath, meshheader, meshdata, toblender, operator) + fileID.close + + bpy.context.scene.frame_start=1 + bpy.context.scene.frame_end=maxframe + bpy.context.scene.frame_current=1 + anchor = bpy.data.objects.new('Empty', None) + anchor.select = True + bpy.context.scene.objects.link(anchor) + for ob in imported: + ob.parent = anchor + bpy.context.scene.update() + print ("Created a empty Object as 'Grip' where all imported Objects are parented to") + print ("To move the complete Meshes only select this empty Object and move it") + print ("All Done, have a good Day :-)\n\n") + return + +def G3DSaver(filepath, context, toglest, operator): + print ("\nNow Exporting File: " + filepath) + + objs = context.selected_objects + if len(objs) == 0: + objs = bpy.data.objects + + #get real meshcount as len(bpy.data.meshes) holds also old meshes + meshCount = 0 + for obj in objs: + if obj.type == 'MESH': + meshCount += 1 + if obj.mode != 'OBJECT': # we want to be in object mode + print("ERROR: mesh not in object mode") + operator.report({'ERROR'}, "mesh not in object mode") + return -1 + + if meshCount == 0: + print("ERROR: no meshes found") + operator.report({'ERROR'}, "no meshes found") + return -1 + + fileID = open(filepath,"wb") + # G3DHeader v4 + fileID.write(struct.pack("<3cB", b'G', b'3', b'D', 4)) + # G3DModelHeaderv4 + fileID.write(struct.pack(" 0: + # we have a texture, hopefully + material = mesh.materials[0] + slot = material.texture_slots[0] + # only look for other textures when we have diffuse + if slot and slot.texture.type=='IMAGE' and len(mesh.uv_textures)>0: + diffuseColor = material.diffuse_color + specularColor = material.specular_color + opacity = material.alpha + textures = 1 + texnames = [] + texnames.append(bpy.path.basename(slot.texture.image.filepath)) + # specular and normal + for i in range(1, 3): + slot = material.texture_slots[i] + if slot and slot.texture.type=='IMAGE': + texnames.append(bpy.path.basename(slot.texture.image.filepath)) + textures |= 1 << i + + else: + print("WARNING: first texture slot in first material isn't of type IMAGE or it's not unwrapped, texture ignored") + operator.report({'WARNING'}, "first texture slot in first material isn't of type IMAGE or it's not unwrapped, texture ignored") + #continue without texture + + meshname = mesh.name + frameCount = context.scene.frame_end - context.scene.frame_start +1 + realFaceCount = 0 # real face count (triangles) + indices=[] # list of indices + newverts=[] # list of vertex indices which need to be duplicated + uvlist = [] # list of texcoords + mesh.update(calc_tessface=True) # tesselate n-polygons to triangles & quads + if textures: + uvtex = mesh.tessface_uv_textures[0] + uvlist[:] = [[0]*2 for i in range(len(mesh.vertices))] + # blender allows to have multiple texcoords per vertex, + # in g3d format every vertex can only have one texcoord + # -> duplicate vertex + # the dictionary/map vdict collects all the stuff + # index to "unique" vertices from blender + # -> tuple( list of texcoords, list of indices to the duplicated vertex ) + vdict = dict() + nextIndex = len(mesh.vertices) + for face in mesh.tessfaces: + # when a vertex is duplicated it gets a new index, so the + # triple of indices describing the face is different too + faceindices = [] + realFaceCount += 1 + uvdata = uvtex.data[face.index] + for i in range(3): + #closure, got rid of copy&paste, still looking weird + def getTexCoords(): + nonlocal nextIndex, vdict, uvlist, newverts + vindex = face.vertices[i] + if vindex not in vdict: # new vertex -> add it + vdict[vindex] = [uvdata.uv[i]], [vindex] + uvlist[vindex] = uvdata.uv[i] # that's a (s,t)-pair + else: + found = False + idx = 0 + for ele in vdict[vindex][0]: + if uvdata.uv[i][0] == ele[0] and uvdata.uv[i][1] == ele[1]: + found = True + break + idx += 1 + if found: # same vertex and texcoord before + # it could be a different index now, the index of a new + # duplicated vertex + #vindex = vdict[vindex][1][ vdict[vindex][0].index(uvdata.uv[i]) ] + vindex = vdict[vindex][1][idx] + else: # same vertex as before but with different texcoord -> duplicate + vdict[vindex][0].append(uvdata.uv[i]) + vdict[vindex][1].append(nextIndex) + + # duplicate vertex because it takes part in different faces + # with different texcoords + newverts.append(vindex) + uvlist.append(uvdata.uv[i]) + # new index for the duplicated vertex + vindex = nextIndex + nextIndex += 1 + + faceindices.append(vindex) + getTexCoords() + indices.extend(faceindices) + + if len(face.vertices) == 4: + faceindices = [] + realFaceCount += 1 + for i in [0,2,3]: + getTexCoords() + indices.extend(faceindices) + else: + for face in mesh.tessfaces: + realFaceCount += 1 + indices.extend(face.vertices[0:3]) + if len(face.vertices) == 4: + realFaceCount += 1 + # new face because quad got split + indices.append(face.vertices[0]) + indices.append(face.vertices[2]) + indices.append(face.vertices[3]) + + + # abort when no triangles as it crashs g3dviewer + if realFaceCount == 0: + print("ERROR: no triangles found") + operator.report({'ERROR'}, "no triangles found") + fileID.close() + return -1 + indexCount = realFaceCount * 3 + vertexCount = len(mesh.vertices) + len(newverts) + specularPower = 9.999999 # unused, same as old exporter + properties = 0 + if mesh.g3d_customColor: + properties |= 1 + if mesh.show_double_sided: + properties |= 2 + if mesh.g3d_noSelect: + properties |= 4 + if mesh.g3d_glow: + properties |= 8 + + #MeshData + vertices = [] + normals = [] + fcurrent = context.scene.frame_current + for i in range(context.scene.frame_start, context.scene.frame_end+1): + context.scene.frame_set(i) + #FIXME: not sure what's better: PREVIEW or RENDER settings + m = obj.to_mesh(context.scene, True, 'RENDER') + m.transform(obj.matrix_world) # apply object-mode transformations + + if toglest: + # rotate from blender to glest orientation + m.transform( Matrix( ((1,0,0,0),(0,0,1,0),(0,-1,0,0),(0,0,0,1)) ) ) + # transform normals too + m.calc_normals() + + for vertex in m.vertices: + vertices.extend(vertex.co) + normals.extend(vertex.normal) + + # duplicate vertices and corresponding normals, for every frame + for nv in newverts: + vertices.extend(m.vertices[nv].co) + normals.extend(m.vertices[nv].normal) + + context.scene.frame_set(fcurrent) + + if mesh.g3d_fullyOpaque: + opacity = 1.0 + + # MeshHeader + fileID.write(struct.pack("<64s3I8f2I", + bytes(meshname, "ascii"), + frameCount, vertexCount, indexCount, + diffuseColor[0], diffuseColor[1], diffuseColor[2], + specularColor[0], specularColor[1], specularColor[2], + specularPower, opacity, + properties, textures + )) + #Texture names + if textures: # only when we have textures + for i in range(len(texnames)): + fileID.write(struct.pack("<64s", bytes(texnames[i], "ascii"))) + + # see G3DMeshdataV4 + vertex_format = "<%if" % int(frameCount * vertexCount * 3) + normals_format = "<%if" % int(frameCount * vertexCount * 3) + texturecoords_format = "<%if" % int(vertexCount * 2) + indices_format = "<%iI" % int(indexCount) + + fileID.write(struct.pack(vertex_format, *vertices)) + fileID.write(struct.pack(normals_format, *normals)) + + # texcoords + if textures: # only when we have textures + texcoords = [] + for uv in uvlist: + texcoords.extend(uv) + fileID.write(struct.pack(texturecoords_format, *texcoords)) + + fileID.write(struct.pack(indices_format, *indices)) + + fileID.close() + return 0 + + +#---=== Register === +class G3DPanel(bpy.types.Panel): + #bl_idname = "OBJECT_PT_G3DPanel" + bl_label = "G3D properties" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "data" + + @classmethod + def poll(cls, context): + return (context.object is not None and context.object.type == 'MESH') + + def draw(self, context): + self.layout.prop(context.object.data, "g3d_customColor") + self.layout.prop(context.object.data, "show_double_sided", text="double sided") + self.layout.prop(context.object.data, "g3d_noSelect") + self.layout.prop(context.object.data, "g3d_fullyOpaque") + self.layout.prop(context.object.data, "g3d_glow") + +class ImportG3D(bpy.types.Operator, ImportHelper): + '''Load a G3D file''' + bl_idname = "importg3d.g3d" + bl_label = "Import G3D" + + filename_ext = ".g3d" + filter_glob = StringProperty(default="*.g3d", options={'HIDDEN'}) + + toblender = bpy.props.BoolProperty( + name="rotate to Blender orientation", + description="Rotate meshes from Glest to Blender orientation", + default=True) + + def execute(self, context): + try: + G3DLoader(self.filepath, self.toblender, self) + except: + import traceback + traceback.print_exc() + + return {'CANCELLED'} + + return {'FINISHED'} + +class ExportG3D(bpy.types.Operator, ExportHelper): + '''Save a G3D file''' + bl_idname = "exportg3d.g3d" + bl_label = "Export G3D" + + filename_ext = ".g3d" + filter_glob = StringProperty(default="*.g3d", options={'HIDDEN'}) + + #export options + showg3d = bpy.props.BoolProperty( + name="show G3D afterwards", + description=("Run g3dviewer to show G3D after export. " + "g3dviewer needs to be in the scripts directory, " + "otherwise the associated program of .g3d is run."), + default=False) + toglest = bpy.props.BoolProperty( + name="rotate to glest orientation", + description="Rotate meshes from Blender to Glest orientation", + default=True) + + def execute(self, context): + try: + res = G3DSaver(self.filepath, context, self.toglest, self) + if res==0 and self.showg3d: + print("opening g3dviewer with " + self.filepath) + scriptsdir = bpy.utils.script_path_user() + dname = os.path.dirname(self.filepath) + found = False + for f in os.listdir(scriptsdir): + if "g3dviewer" in f: + f = os.path.join(scriptsdir, f) + if os.path.isfile(f) and os.access(f, os.X_OK): + cmd = [f, self.filepath] + print(cmd) + subprocess.Popen(cmd, cwd=dname) + found = True + + # try default associated program + if not found: + if os.name == 'posix': + # xdg-open is only a shell script which delegates the job to a + # desktop specific program, e.g. if DE=kde than kde-open + # needs DE environment variable set, otherwise it just throws it + # at the browser, which is not very helpful + print("running xdg-open "+self.filepath) + subprocess.Popen(['xdg-open', self.filepath], cwd=dname) + elif os.name == 'mac': + subprocess.Popen(['open', self.filepath], cwd=dname) + elif os.name == 'nt': + #os.startfile(self.filepath) # no way to change dir + subprocess.Popen(['cmd', '/C', 'start', self.filepath], cwd=dname) + + except: + import traceback + traceback.print_exc() + + return {'CANCELLED'} + + return {'FINISHED'} + +def menu_func_import(self, context): + self.layout.operator(ImportG3D.bl_idname, text="Glest 3D File (.g3d)") + +def menu_func_export(self, context): + self.layout.operator(ExportG3D.bl_idname, text="Glest 3D File (.g3d)") + +def register(): + # custom mesh properties + bpy.types.Mesh.g3d_customColor = bpy.props.BoolProperty( + name="team color", + description="replace alpha channel of texture with team color") + bpy.types.Mesh.g3d_noSelect = bpy.props.BoolProperty( + name="non-selectable", + description="click on mesh doesn't select unit") + bpy.types.Mesh.g3d_fullyOpaque = bpy.props.BoolProperty( + name="fully opaque", + description="sets opacity to 1.0, ignoring what's set in materials") + bpy.types.Mesh.g3d_glow = bpy.props.BoolProperty( + name="glow", + description="let objects glow like particles") + + bpy.utils.register_module(__name__) + + bpy.types.INFO_MT_file_import.append(menu_func_import) + bpy.types.INFO_MT_file_export.append(menu_func_export) + + +def unregister(): + bpy.utils.unregister_module(__name__) + + bpy.types.INFO_MT_file_import.remove(menu_func_import) + bpy.types.INFO_MT_file_export.remove(menu_func_export) + +if __name__ == '__main__': + register() +# main() + + #for obj in bpy.data.objects: + # if obj.type == 'MESH': + # obj.select = True + # bpy.ops.object.delete() + #G3DLoader("import.g3d", True, None) + + #for obj in bpy.context.selected_objects: + # obj.select = False # deselect everything, so we get it all + #G3DSaver("test.g3d", bpy.context) -def G3DSaverV4(filename): - return -########################################################################### -# Complete GUI Part of The Wizard -########################################################################### -# Events that can occure by pressing the Buttons -EVENT_LOADG3D=2 -EVENT_SAVEG3DV3=3 -EVENT_SAVEG3DV4=4 -EVENT_EXIT=100 -########################################################################### -# GUI eventhandler -########################################################################### -def event(evt, val): - if evt == Blender.Draw.ESCKEY and not val: Blender.Draw.Exit() -def button_event(evt): - global EVENT_LOAD_G3D,EVENT_SAVE_G3DV3,EVENT_SAVE_G3DV4,EVENT_EXIT - if evt == EVENT_EXIT: Exit() - if evt == EVENT_LOADG3D: - defaultname = os.sep + ".g3d" -#I use this defaultnames only for development to have short ways to models -#if u want make a path to your models here and comment the above defaultname out. -#Be careful to not move the start of the Line because it matters in python -# defaultname="I:/glest/glest_game/techs/magitech/factions/magic/units/magic_armor/models/magic_armor_walking.g3d" -# defaultname="I:/glest/glest_game/techs/magitech/factions/.g3d" -# defaultname="I:/entwicklung/blenderexport/test/swordman_sample/swordman.g3d" - FileSelector(G3DLoader, "G3D to load", defaultname) - Blender.Redraw() - if evt==EVENT_SAVEG3DV3: - defaultname = Blender.sys.makename(Blender.Get("filename"),".g3d",1) - FileSelector(G3DSaverV3, "G3D V3 to save", defaultname) - if evt==EVENT_SAVEG3DV4: - defaultname = Blender.sys.makename(Blender.Get("filename"),".g3d",1) - FileSelector(G3DSaverV4, "G3D V4 to save", defaultname) -########################################################################### -# GUI Screenmask as a nice looking feature i Center the Mask -########################################################################### -def gui(): - global EVENT_LOADG3D,EVENT_SAVEG3DV3,EVENT_SAVEG3DV4,EVENT_EXIT - xmiddle= GetScreenSize()[0] / 2 #calculate horizontal middle of the screen - #Clearing the Screen all here needs imported BGL + DRAW - glClearColor(0.0, 0.0, 0.0,1) - glClear(GL_COLOR_BUFFER_BIT) - # logo - homedir = Blender.Get("homedir") - Logo = Load(homedir+ os.sep + "scripts" + os.sep + "g3d_logo.png") # Load Logo file - glEnable(GL_BLEND) - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) - Image(Logo,(xmiddle-(Logo.getSize()[0]/2)),20) - glDisable(GL_BLEND) - #Title - tbuffer= "G3D Import Wizard supporting V3 / V4 models" - xpos = xmiddle - (GetStringWidth(tbuffer) /2) - glColor3f(1, 0, 0) - glRasterPos2d(xpos, 70) - Text(tbuffer) - tbuffer= "Please view any Errors / Info in the Blender Console" - xpos = xmiddle - (GetStringWidth(tbuffer) /2) - glColor3f(1, 1, 0) - glRasterPos2d(xpos, 55) - Text(tbuffer) - #Buttons - Button("Load G3D",EVENT_LOADG3D , xmiddle-140, 10, 100, 40) - #Button("Save G3D V3",EVENT_SAVEG3DV3 , xmiddle-100, 10, 100, 40) - #Button("Save G3D V4",EVENT_SAVEG3DV4 , xmiddle, 10, 100, 40) - Button("Exit",EVENT_EXIT , xmiddle+40, 10, 100, 40) -########################################################################### -# Registering GUI events (Activating GUI) THE END -########################################################################### -Register(gui, event, button_event) diff --git a/source/tools/glexemel/g3d_support_b257.py b/source/tools/glexemel/g3d_support_b257.py deleted file mode 100755 index bbabeb60..00000000 --- a/source/tools/glexemel/g3d_support_b257.py +++ /dev/null @@ -1,729 +0,0 @@ -########################################################################### -# Glest Model / Texture / UV / Animation Importer and Exporter -# for the Game Glest that u can find http://www.glest.org -# copyright 2005 By Andreas Becker (seltsamuel@yahoo.de) -# -# Updated Jan 2011 by Mark Vejvoda (SoftCoder) to properly import animations -# from G3D into Blender -# -# Started Date: 07 June 2005 Put Public 20 June 2005 -# Ver: 0.01 Beta Exporter ripped off because work in Progress -# Distributed under the GNU PUBLIC LICENSE for www.megaglest.org and glest.org -########################################################################### -#NOTE: -# Copy this Script AND g3d_logo.png into .Blender\scripts -# directory then start inside blender Scripts window -# "Update Menus" after that this Script here is accesible -# as 'Wizards' G3d Fileformat Im/Exporter -#ToDo: -#Exporter Bughunt he will be rejoined next release -#Maybe Integrate UV Painter to Generate UVMaps from Blender Material and procedural Textures -#will be nice to paint wireframe too, so that one can easyly load into Paintprogram and see where to paint -#(Already possible through Blender functions so at the end of the list :-) ) -########################################################################### - -bl_info = { - "name": "MegaGlest G3D Fileformat Import/Exporter", - "description": "Imports and Exports the Glest fileformat V3/V4 (.g3d)", - "author": "Andreas Becker, Mark Vejvoda, William Zheng", - "version": (1,1), - "blender": (2, 5, 7), - "api": 35622, - 'location': 'File > Import-Export', - "warning": '', - "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\ - "Scripts/Import-Export/MegaGlest_G3D", - "tracker_url": "http://projects.blender.org/tracker/index.php?"\ - "func=detail&aid=", - "category": "Import-Export" -} - -""" -Here an explanation of the V4 Format found at www.glest.org -================================ -1. DATA TYPES -================================ -G3D files use the following data types: -uint8: 8 bit unsigned integer -uint16: 16 bit unsigned integer -uint32: 32 bit unsigned integer -float32: 32 bit floating point -================================ -2. OVERALL STRUCTURE -================================ -- File header -- Model header -- Mesh header -- Texture names -- Mesh data -================================ -2. FILE HEADER -================================ -Code: -struct FileHeader{ - uint8 id[3]; - uint8 version; -}; -This header is shared among all the versions of G3D, it identifies this file as a G3D model and provides information of the version. -id: must be "G3D" -version: must be 4, in binary (not '4') -================================ -3. MODEL HEADER -================================ -Code: -struct ModelHeader{ - uint16 meshCount; - uint8 type; -}; -meshCount: number of meshes in this model -type: must be 0 -================================ -4. MESH HEADER -================================ -There is a mesh header for each mesh, there must be "meshCount" headers in a file but they are not consecutive, texture names and mesh data are stored in between. -Code: -struct MeshHeader{ - uint8 name[64]; - uint32 frameCount; - uint32 vertexCount; - uint32 indexCount; - float32 diffuseColor[3]; - float32 specularColor[3]; - float32 specularPower; - float32 opacity; - uint32 properties; - uint32 textures; -}; -name: name of the mesh -frameCount: number of keyframes in this mesh -vertexCount: number of vertices in each frame -indexCount: number of indices in this mesh (the number of triangles is indexCount/3) -diffuseColor: RGB diffuse color -specularColor: RGB specular color (currently unused) -specularPower: specular power (currently unused) -properties: property flags -Code: -enum MeshPropertyFlag{ - mpfTwoSided= 1, - mpfCustomColor= 2, -}; -mpfTwoSided: meshes in this mesh are rendered by both sides, if this flag is not present only "counter clockwise" faces are rendered -mpfCustomColor: alpha in this model is replaced by a custom color, usually the player color -textures: texture flags, only 0x1 is currently used, indicating that there is a diffuse texture in this mesh. -================================ -4. TEXTURE NAMES -================================ -A list of uint8[64] texture name values. One for each texture in the mesh. If there are no textures in the mesh no texture names are present. In practice since Glest only uses 1 texture for each mesh the number of texture names should be 0 or 1. -================================ -5. MESH DATA -================================ -After each mesh header and texture names the mesh data is placed. -vertices: frameCount * vertexCount * 3, float32 values representing the x, y, z vertex coords for all frames -normals: frameCount * vertexCount * 3, float32 values representing the x, y, z normal coords for all frames -texture coords: vertexCount * 2, float32 values representing the s, t tex coords for all frames (only present if the mesh has 1 texture at least) -indices: indexCount, uint32 values representing the indices -""" -########################################################################### -# Importing Structures needed (must later verify if i need them really all) -########################################################################### -import sys, struct, string, types -from types import * -import os -from os import path -from os.path import dirname - -import bpy -from bpy.props import StringProperty -from io_utils import ImportHelper, ExportHelper -import mathutils -import math - -import re -from string import * -from struct import * - - -########################################################################### -# Variables that are better Global to handle -########################################################################### -imported = [] #List of all imported Objects -toexport = [] #List of Objects to export (actually only meshes) -sceneID = None #Points to the active Blender Scene - -########################################################################### -# Declaring Structures of G3D Format -########################################################################### -class G3DHeader: #Read first 4 Bytes of file should be G3D + Versionnumber - binary_format = "<3cB" - def __init__(self, fileID): - temp = fileID.read(struct.calcsize(self.binary_format)) - data = struct.unpack(self.binary_format,temp) - - #print(type(data)); print(repr(data)) - #self.id = bytes(data[0]).decode() + bytes(data[1]).decode() + bytes(data[2]).decode() - self.id = ''.join(item.decode() for item in data[0:3]) - #self.id = data[0:3] - self.version = data[3] - -class G3DModelHeaderv3: #Read Modelheader in V3 there is only the number of Meshes in file - binary_format = "