finish cleanup
This commit is contained in:
parent
55af8e8406
commit
c0ba209f87
@ -1,7 +1,5 @@
|
|||||||
# bpy. app. debug = True
|
# bpy. app. debug = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "PSX TMesh exporter",
|
"name": "PSX TMesh exporter",
|
||||||
"author": "Schnappy, TheDukeOfZill",
|
"author": "Schnappy, TheDukeOfZill",
|
||||||
@ -13,12 +11,19 @@ bl_info = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
import bmesh
|
import bmesh
|
||||||
|
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
|
||||||
from math import radians, degrees, floor, cos, sin
|
from math import radians, degrees, floor, cos, sin
|
||||||
|
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from bpy.props import (CollectionProperty,
|
from bpy.props import (CollectionProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
BoolProperty,
|
BoolProperty,
|
||||||
@ -31,122 +36,282 @@ from bpy_extras.io_utils import (ExportHelper,
|
|||||||
)
|
)
|
||||||
|
|
||||||
class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
||||||
|
|
||||||
bl_idname = "export_psx.c";
|
bl_idname = "export_psx.c";
|
||||||
|
|
||||||
bl_label = "PSX compatible scene exporter";
|
bl_label = "PSX compatible scene exporter";
|
||||||
|
|
||||||
bl_options = {'PRESET'};
|
bl_options = {'PRESET'};
|
||||||
|
|
||||||
filename_ext = ".c";
|
filename_ext = ".c";
|
||||||
|
|
||||||
exp_Triangulate = BoolProperty(
|
exp_Triangulate = BoolProperty(
|
||||||
|
|
||||||
name="Triangulate meshes ( Destructive ! )",
|
name="Triangulate meshes ( Destructive ! )",
|
||||||
|
|
||||||
description="Triangulate meshes (destructive ! Do not use your original file)",
|
description="Triangulate meshes (destructive ! Do not use your original file)",
|
||||||
|
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
exp_Scale = FloatProperty(
|
exp_Scale = FloatProperty(
|
||||||
|
|
||||||
name="Scale",
|
name="Scale",
|
||||||
|
|
||||||
description="Scale of exported mesh.",
|
description="Scale of exported mesh.",
|
||||||
|
|
||||||
min=1, max=1000,
|
min=1, max=1000,
|
||||||
|
|
||||||
default=65,
|
default=65,
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
exp_Precalc = BoolProperty(
|
exp_Precalc = BoolProperty(
|
||||||
|
|
||||||
name="Use precalculated BGs",
|
name="Use precalculated BGs",
|
||||||
|
|
||||||
description="Set the BGs UV to black",
|
description="Set the BGs UV to black",
|
||||||
|
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
|
||||||
def triangulate_object(obj): # Stolen from here : https://blender.stackexchange.com/questions/45698/triangulate-mesh-in-python/45722#45722
|
def triangulate_object(obj):
|
||||||
|
|
||||||
|
# Triangulate an object's mesh
|
||||||
|
# Source : https://blender.stackexchange.com/questions/45698/triangulate-mesh-in-python/45722#45722
|
||||||
|
|
||||||
me = obj.data
|
me = obj.data
|
||||||
|
|
||||||
# Get a BMesh representation
|
# Get a BMesh representation
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
|
|
||||||
bm.from_mesh(me)
|
bm.from_mesh(me)
|
||||||
|
|
||||||
bmesh.ops.triangulate(bm, faces=bm.faces[:], quad_method=0, ngon_method=0)
|
bmesh.ops.triangulate(bm, faces=bm.faces[:], quad_method=0, ngon_method=0)
|
||||||
|
|
||||||
# Finish up, write the bmesh back to the mesh
|
# Finish up, write the bmesh back to the mesh
|
||||||
bm.to_mesh(me)
|
bm.to_mesh(me)
|
||||||
|
|
||||||
bm.free()
|
bm.free()
|
||||||
# ~ return bm
|
|
||||||
|
|
||||||
def CleanName(strName):
|
def CleanName(strName):
|
||||||
|
|
||||||
|
# Removes specials characters, dots ans space from string
|
||||||
|
|
||||||
name = strName.replace(' ','_')
|
name = strName.replace(' ','_')
|
||||||
|
|
||||||
name = name.replace('.','_')
|
name = name.replace('.','_')
|
||||||
|
|
||||||
name = unicodedata.normalize('NFKD',name).encode('ASCII', 'ignore').decode()
|
name = unicodedata.normalize('NFKD',name).encode('ASCII', 'ignore').decode()
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
def isInPlane(plane, obj):
|
||||||
|
|
||||||
|
# Checks if 'obj' has its coordinates contained between the plane's coordinate.
|
||||||
|
# If 'obj' is partly contained, returns which side (S, W, N, E) it's overlapping.
|
||||||
|
# If 'obj' is not contained in 'plane', returns 0.
|
||||||
|
|
||||||
|
if (
|
||||||
|
(LvlPlanes[plane]['x1'] < LvlObjects[obj]['x1'] and LvlPlanes[plane]['x2'] > LvlObjects[obj]['x2']) and
|
||||||
|
(LvlPlanes[plane]['y1'] < LvlObjects[obj]['y1'] and LvlPlanes[plane]['y2'] > LvlObjects[obj]['y2'])
|
||||||
|
):
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Overlap on the West side of the plane
|
||||||
|
if (
|
||||||
|
( LvlPlanes[plane]['x1'] > LvlObjects[obj]['x1'] and LvlPlanes[plane]['x1'] < LvlObjects[obj]['x2'] ) and
|
||||||
|
( LvlPlanes[plane]['y1'] < LvlObjects[obj]['y1'] and LvlPlanes[plane]['y2'] > LvlObjects[obj]['y2'] )
|
||||||
|
):
|
||||||
|
|
||||||
|
return 4
|
||||||
|
|
||||||
|
# Overlap on the East side of the plane
|
||||||
|
if (
|
||||||
|
( LvlPlanes[plane]['x2'] < LvlObjects[obj]['x2'] and LvlPlanes[plane]['x2'] > LvlObjects[obj]['x1'] ) and
|
||||||
|
( LvlPlanes[plane]['y1'] < LvlObjects[obj]['y1'] and LvlPlanes[plane]['y2'] > LvlObjects[obj]['y2'] )
|
||||||
|
):
|
||||||
|
|
||||||
|
return 6
|
||||||
|
|
||||||
|
# Overlap on the North side of the plane
|
||||||
|
if (
|
||||||
|
( LvlPlanes[plane]['y2'] < LvlObjects[obj]['y2'] and LvlPlanes[plane]['y2'] > LvlObjects[obj]['y1'] ) and
|
||||||
|
( LvlPlanes[plane]['x1'] < LvlObjects[obj]['x1'] and LvlPlanes[plane]['x2'] > LvlObjects[obj]['x2'] )
|
||||||
|
):
|
||||||
|
|
||||||
|
return 8
|
||||||
|
|
||||||
|
# Overlap on the South side of the plane
|
||||||
|
if (
|
||||||
|
( LvlPlanes[plane]['y1'] > LvlObjects[obj]['y1'] and LvlPlanes[plane]['y1'] < LvlObjects[obj]['y2'] ) and
|
||||||
|
( LvlPlanes[plane]['x1'] < LvlObjects[obj]['x1'] and LvlPlanes[plane]['x2'] > LvlObjects[obj]['x2'] )
|
||||||
|
):
|
||||||
|
|
||||||
|
return 2
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def getSepLine(plane, side):
|
||||||
|
|
||||||
|
# Construct the line used for BSP generation from 'plane' 's coordinates, on specified side (S, W, N, E)
|
||||||
|
# Returns an array of 3 values
|
||||||
|
|
||||||
|
if side == 'S':
|
||||||
|
|
||||||
|
return [ LvlPlanes[plane]['x1'], LvlPlanes[plane]['y1'], LvlPlanes[plane]['x2'], LvlPlanes[plane]['y1'] ]
|
||||||
|
|
||||||
|
if side == 'N':
|
||||||
|
|
||||||
|
return [ LvlPlanes[plane]['x1'], LvlPlanes[plane]['y2'], LvlPlanes[plane]['x2'], LvlPlanes[plane]['y2'] ]
|
||||||
|
|
||||||
|
if side == 'W':
|
||||||
|
|
||||||
|
return [ LvlPlanes[plane]['x1'], LvlPlanes[plane]['y1'], LvlPlanes[plane]['x1'], LvlPlanes[plane]['y2'] ]
|
||||||
|
|
||||||
|
if side == 'E':
|
||||||
|
|
||||||
|
return [ LvlPlanes[plane]['x2'], LvlPlanes[plane]['y1'], LvlPlanes[plane]['x2'], LvlPlanes[plane]['y2'] ]
|
||||||
|
|
||||||
|
def checkLine(lineX1, lineY1 ,lineX2 ,lineY2, objX1, objY1, objX2, objY2):
|
||||||
|
|
||||||
|
# Returns wether object spanning from objXY1 to objXY2 is Back, Front, Same or Intersecting the line
|
||||||
|
# defined by points (lineXY1, lineXY2)
|
||||||
|
|
||||||
|
val1 = ( objX1 - lineX1 ) * ( lineY2-lineY1 ) - ( objY1 - lineY1 ) * ( lineX2 - lineX1 )
|
||||||
|
|
||||||
|
# rounding to avoid false positives
|
||||||
|
|
||||||
|
val1 = round(val1, 4)
|
||||||
|
|
||||||
|
val2 = ( objX2 - lineX1 ) * ( lineY2-lineY1 ) - ( objY2 - lineY1 ) * ( lineX2 - lineX1 )
|
||||||
|
|
||||||
|
val2 = round(val2, 4)
|
||||||
|
|
||||||
|
if ( (val1 > 0) and (val2 > 0) ):
|
||||||
|
|
||||||
|
return "front"
|
||||||
|
|
||||||
|
elif ( (val1 < 0) and (val2 < 0) ):
|
||||||
|
|
||||||
|
return "back"
|
||||||
|
|
||||||
|
elif ( (val1 == 0) and (val2 == 0) ):
|
||||||
|
|
||||||
|
return "same"
|
||||||
|
|
||||||
|
elif (
|
||||||
|
( (val1>0) and (val2==0) ) or
|
||||||
|
( (val1==0) and (val2>0) )
|
||||||
|
):
|
||||||
|
|
||||||
|
return "front"
|
||||||
|
|
||||||
|
elif (
|
||||||
|
( (val1<0) and (val2==0) ) or
|
||||||
|
( (val1==0) and (val2<0) )
|
||||||
|
):
|
||||||
|
|
||||||
|
return "back"
|
||||||
|
|
||||||
|
elif (
|
||||||
|
( (val1<0) and (val2>0) ) or
|
||||||
|
( (val1>0) and (val2<0) )
|
||||||
|
):
|
||||||
|
|
||||||
|
return "intersect"
|
||||||
|
|
||||||
# Leave edit mode to avoid errors
|
# Leave edit mode to avoid errors
|
||||||
|
|
||||||
bpy.ops.object.mode_set(mode='OBJECT')
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
# triangulate objects of type mesh
|
# If set, triangulate objects of type mesh
|
||||||
|
|
||||||
if self.exp_Triangulate:
|
if self.exp_Triangulate:
|
||||||
|
|
||||||
for o in range(len(bpy.data.objects)):
|
for o in range(len(bpy.data.objects)):
|
||||||
|
|
||||||
if bpy.data.objects[o].type == 'MESH':
|
if bpy.data.objects[o].type == 'MESH':
|
||||||
|
|
||||||
triangulate_object(bpy.data.objects[o])
|
triangulate_object(bpy.data.objects[o])
|
||||||
|
|
||||||
# ~ obj = bpy.data.objects[bpy.data.objects[o].name]
|
# Set Scale
|
||||||
|
|
||||||
# ~ tm = obj.to_mesh(bpy.context.scene, False, 'PREVIEW')
|
|
||||||
|
|
||||||
# ~ work_meshes.append(tm)
|
|
||||||
|
|
||||||
scale = self.exp_Scale
|
scale = self.exp_Scale
|
||||||
|
|
||||||
# get working directory path
|
# Get working directory path
|
||||||
|
|
||||||
filepath = bpy.data.filepath
|
filepath = bpy.data.filepath
|
||||||
|
|
||||||
folder = os.path.dirname(bpy.path.abspath(filepath))
|
folder = os.path.dirname(bpy.path.abspath(filepath))
|
||||||
|
|
||||||
dirpath = os.path.join(folder, "TIM")
|
dirpath = os.path.join(folder, "TIM")
|
||||||
|
|
||||||
|
### Export pre-calculated backgrounds
|
||||||
|
|
||||||
camAngles = []
|
camAngles = []
|
||||||
|
|
||||||
defaultCam = 'NULL'
|
defaultCam = 'NULL'
|
||||||
|
|
||||||
# if using precalculated BG, render and export them to ./TIM/
|
# If using precalculated BG, render and export them to ./TIM/
|
||||||
|
|
||||||
if self.exp_Precalc:
|
if self.exp_Precalc:
|
||||||
|
|
||||||
# create folder if !exist
|
# Create folder if it doesn't exist
|
||||||
|
|
||||||
os.makedirs(dirpath, exist_ok = 1)
|
os.makedirs(dirpath, exist_ok = 1)
|
||||||
|
|
||||||
# file format config
|
# Set file format config
|
||||||
|
|
||||||
bpy.context.scene.render.image_settings.file_format = 'PNG'
|
bpy.context.scene.render.image_settings.file_format = 'PNG'
|
||||||
bpy.context.scene.render.image_settings.quality = 100
|
bpy.context.scene.render.image_settings.quality = 100
|
||||||
bpy.context.scene.render.image_settings.compression = 0
|
bpy.context.scene.render.image_settings.compression = 0
|
||||||
bpy.context.scene.render.image_settings.color_depth = '8'
|
bpy.context.scene.render.image_settings.color_depth = '8'
|
||||||
|
|
||||||
# get current cam
|
# Get active cam
|
||||||
|
|
||||||
cam = bpy.context.scene.camera
|
cam = bpy.context.scene.camera
|
||||||
|
|
||||||
# store cam location and rot for restoration later
|
# Find default cam, and cameras in camPath
|
||||||
# ~ originLoc = cam.location
|
|
||||||
# ~ originRot = cam.rotation_euler
|
|
||||||
|
|
||||||
for o in bpy.data.objects:
|
for o in bpy.data.objects:
|
||||||
|
|
||||||
if o.type == 'CAMERA' and o.data.get('isDefault'):
|
if o.type == 'CAMERA' and o.data.get('isDefault'):
|
||||||
|
|
||||||
defaultCam = o.name
|
defaultCam = o.name
|
||||||
|
|
||||||
if o.type == 'CAMERA' and o.name.startswith("camPath"):
|
if o.type == 'CAMERA' and o.name.startswith("camPath"):
|
||||||
|
|
||||||
# set cam as active - could be useful if multiple cam are present
|
# Set camera as active
|
||||||
|
|
||||||
bpy.context.scene.camera = o
|
bpy.context.scene.camera = o
|
||||||
|
|
||||||
# set cam Rot/Loc to empty rot/loc
|
# Render and save image
|
||||||
# ~ cam.location = o.location
|
|
||||||
# ~ cam.rotation_euler = o.rotation_euler
|
|
||||||
|
|
||||||
# apply 90degrees rotation on local X axis, as EMPTYs are pointing to -Z (bottom of the screen) by default
|
|
||||||
# ~ cam.rotation_euler.rotate_axis('X', radians(90))
|
|
||||||
|
|
||||||
# render and save image
|
|
||||||
bpy.ops.render.render()
|
bpy.ops.render.render()
|
||||||
|
|
||||||
bpy.data.images["Render Result"].save_render(folder + os.sep + "TIM" + os.sep + "bg_" + CleanName(o.name) + "." + str(bpy.context.scene.render.image_settings.file_format).lower())
|
bpy.data.images["Render Result"].save_render(folder + os.sep + "TIM" + os.sep + "bg_" + CleanName(o.name) + "." + str(bpy.context.scene.render.image_settings.file_format).lower())
|
||||||
|
|
||||||
|
# Add camera object to camAngles
|
||||||
|
|
||||||
camAngles.append(o)
|
camAngles.append(o)
|
||||||
|
|
||||||
|
|
||||||
# set cam back to original pos/rot
|
### Start writing output file
|
||||||
# ~ cam.location = originLoc
|
|
||||||
# ~ cam.rotation_euler = originRot
|
# Open file
|
||||||
|
|
||||||
f = open(os.path.normpath(self.filepath),"w+")
|
f = open(os.path.normpath(self.filepath),"w+")
|
||||||
|
|
||||||
# write BODY struct def
|
## Add C structures definitions
|
||||||
|
|
||||||
|
# BODY
|
||||||
|
|
||||||
f.write("typedef struct {\n" +
|
f.write("typedef struct {\n" +
|
||||||
"\tVECTOR gForce;\n" +
|
"\tVECTOR gForce;\n" +
|
||||||
"\tVECTOR position;\n" +
|
"\tVECTOR position;\n" +
|
||||||
@ -158,7 +323,8 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
"\tint restitution; \n" +
|
"\tint restitution; \n" +
|
||||||
"\t} BODY;\n\n")
|
"\t} BODY;\n\n")
|
||||||
|
|
||||||
# VERTEX ANIM struct
|
# VANIM
|
||||||
|
|
||||||
f.write("typedef struct { \n" +
|
f.write("typedef struct { \n" +
|
||||||
"\tint nframes; // number of frames e.g 20\n" +
|
"\tint nframes; // number of frames e.g 20\n" +
|
||||||
"\tint nvert; // number of vertices e.g 21\n" +
|
"\tint nvert; // number of vertices e.g 21\n" +
|
||||||
@ -170,13 +336,15 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
# ~ "\tSVECTOR normals[]; // vertex pos as SVECTORs e.g 20 * 21 SVECTORS\n" +
|
# ~ "\tSVECTOR normals[]; // vertex pos as SVECTORs e.g 20 * 21 SVECTORS\n" +
|
||||||
"\t} VANIM;\n\n")
|
"\t} VANIM;\n\n")
|
||||||
|
|
||||||
# PRIM struc
|
# PRIM
|
||||||
|
|
||||||
f.write("typedef struct {\n" +
|
f.write("typedef struct {\n" +
|
||||||
"\tVECTOR order;\n" +
|
"\tVECTOR order;\n" +
|
||||||
"\tint code; // Same as POL3/POL4 codes : Code (F3 = 1, FT3 = 2, G3 = 3, GT3 = 4) Code (F4 = 5, FT4 = 6, G4 = 7, GT4 = 8)\n" +
|
"\tint code; // Same as POL3/POL4 codes : Code (F3 = 1, FT3 = 2, G3 = 3, GT3 = 4) Code (F4 = 5, FT4 = 6, G4 = 7, GT4 = 8)\n" +
|
||||||
"\t} PRIM;\n\n")
|
"\t} PRIM;\n\n")
|
||||||
|
|
||||||
# MESH struct
|
# MESH
|
||||||
|
|
||||||
f.write("typedef struct { \n"+
|
f.write("typedef struct { \n"+
|
||||||
"\tTMESH * tmesh;\n" +
|
"\tTMESH * tmesh;\n" +
|
||||||
"\tPRIM * index;\n" +
|
"\tPRIM * index;\n" +
|
||||||
@ -198,38 +366,49 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
"\tVANIM * anim;\n" +
|
"\tVANIM * anim;\n" +
|
||||||
"\t} MESH;\n\n")
|
"\t} MESH;\n\n")
|
||||||
|
|
||||||
# CAM POSITION struct
|
# CAMPOS
|
||||||
|
|
||||||
f.write("typedef struct {\n" +
|
f.write("typedef struct {\n" +
|
||||||
"\tVECTOR pos;\n" +
|
"\tVECTOR pos;\n" +
|
||||||
"\tSVECTOR rot;\n" +
|
"\tSVECTOR rot;\n" +
|
||||||
"\t} CAMPOS;\n\n" +
|
"\t} CAMPOS;\n\n" +
|
||||||
"\n// Blender cam ~= PSX cam with these settings : NTSC - 320x240, PAL 320x256, pixel ratio 1:1, cam focal length : perspective 90° ( 16 mm ))\n\n")
|
"\n// Blender cam ~= PSX cam with these settings : NTSC - 320x240, PAL 320x256, pixel ratio 1:1, cam focal length : perspective 90° ( 16 mm ))\n\n")
|
||||||
|
|
||||||
# CAM ANGLE
|
# CAMANGLE
|
||||||
|
|
||||||
f.write("typedef struct {\n" +
|
f.write("typedef struct {\n" +
|
||||||
"\tCAMPOS * campos;\n" +
|
"\tCAMPOS * campos;\n" +
|
||||||
"\tTIM_IMAGE * BGtim;\n" +
|
"\tTIM_IMAGE * BGtim;\n" +
|
||||||
"\tunsigned long * tim_data;\n" +
|
"\tunsigned long * tim_data;\n" +
|
||||||
"\t} CAMANGLE;\n\n")
|
"\t} CAMANGLE;\n\n")
|
||||||
|
|
||||||
# CAM PATH struct
|
# CAMPATH
|
||||||
|
|
||||||
f.write("typedef struct {\n" +
|
f.write("typedef struct {\n" +
|
||||||
"\tshort len, cursor, pos;\n" +
|
"\tshort len, cursor, pos;\n" +
|
||||||
"\tVECTOR points[];\n" +
|
"\tVECTOR points[];\n" +
|
||||||
"\t} CAMPATH;\n\n")
|
"\t} CAMPATH;\n\n")
|
||||||
|
|
||||||
# NODE struc
|
# NODE
|
||||||
f.Write("typedef struct {\n" +
|
|
||||||
|
f.write("typedef struct {\n" +
|
||||||
"\tMESH * curPlane;\n" +
|
"\tMESH * curPlane;\n" +
|
||||||
"\tMESH * siblings[];" +
|
"\tMESH * siblings[];\n" +
|
||||||
"\tMESH * objects[];" +
|
"\tMESH * objects[];\n" +
|
||||||
"\t} NODE;\n\n")
|
"\t} NODE;\n\n")
|
||||||
|
|
||||||
|
## Camera setup
|
||||||
|
|
||||||
|
# List of points defining the camera path
|
||||||
|
|
||||||
camPathPoints = []
|
camPathPoints = []
|
||||||
|
|
||||||
|
# Define first mesh. Will be used as default if no properties are found in meshes
|
||||||
|
|
||||||
first_mesh = CleanName(bpy.data.meshes[0].name)
|
first_mesh = CleanName(bpy.data.meshes[0].name)
|
||||||
|
|
||||||
# set camera position and rotation in the scene
|
# Set camera position and rotation in the scene
|
||||||
|
|
||||||
for o in range(len(bpy.data.objects)):
|
for o in range(len(bpy.data.objects)):
|
||||||
if bpy.data.objects[o].type == 'CAMERA' and bpy.data.objects[o].data.get('isDefault'):
|
if bpy.data.objects[o].type == 'CAMERA' and bpy.data.objects[o].data.get('isDefault'):
|
||||||
defaultCam = bpy.data.objects[o].name
|
defaultCam = bpy.data.objects[o].name
|
||||||
@ -239,13 +418,18 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
"\t{" + str(round(-(degrees(bpy.data.objects[o].rotation_euler.x)-90)/360 * 4096)) + "," + str(round(degrees(bpy.data.objects[o].rotation_euler.z)/360 * 4096)) + "," + str(round(-(degrees(bpy.data.objects[o].rotation_euler.y))/360 * 4096)) + "}\n" +
|
"\t{" + str(round(-(degrees(bpy.data.objects[o].rotation_euler.x)-90)/360 * 4096)) + "," + str(round(degrees(bpy.data.objects[o].rotation_euler.z)/360 * 4096)) + "," + str(round(-(degrees(bpy.data.objects[o].rotation_euler.y))/360 * 4096)) + "}\n" +
|
||||||
"};\n\n")
|
"};\n\n")
|
||||||
|
|
||||||
# find camStart and camEnd empties for camera trajectory
|
# Find camera path points and append them to camPathPoints[]
|
||||||
|
|
||||||
if bpy.data.objects[o].type == 'CAMERA' :
|
if bpy.data.objects[o].type == 'CAMERA' :
|
||||||
if bpy.data.objects[o].name.startswith("camPath") and not bpy.data.objects[o].data.get('isDefault'):
|
if bpy.data.objects[o].name.startswith("camPath") and not bpy.data.objects[o].data.get('isDefault'):
|
||||||
camPathPoints.append(bpy.data.objects[o].name)
|
camPathPoints.append(bpy.data.objects[o].name)
|
||||||
|
|
||||||
|
# Write the CAMPATH structure
|
||||||
|
|
||||||
if camPathPoints:
|
if camPathPoints:
|
||||||
|
|
||||||
|
# Populate with points found above
|
||||||
|
|
||||||
# ~ camPathPoints = list(reversed(camPathPoints))
|
# ~ camPathPoints = list(reversed(camPathPoints))
|
||||||
|
|
||||||
for p in range(len(camPathPoints)):
|
for p in range(len(camPathPoints)):
|
||||||
@ -259,15 +443,24 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
if p != len(camPathPoints) - 1:
|
if p != len(camPathPoints) - 1:
|
||||||
f.write(",\n")
|
f.write(",\n")
|
||||||
f.write("\n\t}\n};\n\n")
|
f.write("\n\t}\n};\n\n")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
# If no camera path points are found, use default
|
||||||
|
|
||||||
f.write("CAMPATH camPath = {\n" +
|
f.write("CAMPATH camPath = {\n" +
|
||||||
"\t0,\n" +
|
"\t0,\n" +
|
||||||
"\t0,\n" +
|
"\t0,\n" +
|
||||||
"\t0\n" +
|
"\t0\n" +
|
||||||
"};\n\n")
|
"};\n\n")
|
||||||
# Lights : max 3 sunlamp, no space coords
|
|
||||||
|
## Lighting setup
|
||||||
|
|
||||||
|
# Light sources will be similar to Blender's sunlamp
|
||||||
|
# A maximum of 3 light sources will be used
|
||||||
|
|
||||||
# LLM : Local Light Matrix
|
# LLM : Local Light Matrix
|
||||||
|
|
||||||
if len(bpy.data.lamps) is not None:
|
if len(bpy.data.lamps) is not None:
|
||||||
|
|
||||||
# ~ f.write( "static MATRIX lgtmat = {\n" +
|
# ~ f.write( "static MATRIX lgtmat = {\n" +
|
||||||
@ -282,15 +475,15 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
f.write( "static MATRIX lgtmat = {\n")
|
f.write( "static MATRIX lgtmat = {\n")
|
||||||
|
|
||||||
for l in range(len(bpy.data.lamps)):
|
for l in range(len(bpy.data.lamps)):
|
||||||
## intensity
|
|
||||||
|
# Lightsource energy
|
||||||
|
|
||||||
energy = int(bpy.data.lamps[l].energy * 4096)
|
energy = int(bpy.data.lamps[l].energy * 4096)
|
||||||
|
|
||||||
# Euler based
|
# Get lightsource's world orientation
|
||||||
|
|
||||||
# get a direction vector from world matrix
|
|
||||||
lightdir = bpy.data.objects[bpy.data.lamps[l].name].matrix_world * Vector((0,0,-1,0))
|
lightdir = bpy.data.objects[bpy.data.lamps[l].name].matrix_world * Vector((0,0,-1,0))
|
||||||
|
|
||||||
|
|
||||||
f.write(
|
f.write(
|
||||||
"\t" + str(int(lightdir.x * energy)) + "," +
|
"\t" + str(int(lightdir.x * energy)) + "," +
|
||||||
"\t" + str(int(-lightdir.z * energy)) + "," +
|
"\t" + str(int(-lightdir.z * energy)) + "," +
|
||||||
@ -300,6 +493,8 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
if l != len(bpy.data.lamps) - 1:
|
if l != len(bpy.data.lamps) - 1:
|
||||||
f.write(",\n")
|
f.write(",\n")
|
||||||
|
|
||||||
|
# If less than 3 light sources exist in blender, fill the matrix with 0s.
|
||||||
|
|
||||||
if pad:
|
if pad:
|
||||||
f.write(",\n")
|
f.write(",\n")
|
||||||
while cnt < pad:
|
while cnt < pad:
|
||||||
@ -311,6 +506,7 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
f.write("\n\t};\n\n")
|
f.write("\n\t};\n\n")
|
||||||
|
|
||||||
# LCM : Local Color Matrix
|
# LCM : Local Color Matrix
|
||||||
|
|
||||||
f.write( "static MATRIX cmat = {\n")
|
f.write( "static MATRIX cmat = {\n")
|
||||||
|
|
||||||
LCM = []
|
LCM = []
|
||||||
@ -323,12 +519,16 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
while len(LCM) < 9:
|
while len(LCM) < 9:
|
||||||
LCM.append('0')
|
LCM.append('0')
|
||||||
|
|
||||||
|
# Write LC matrix
|
||||||
|
|
||||||
f.write(
|
f.write(
|
||||||
"\t" + LCM[0] + "," + LCM[3] + "," + LCM[6] + ",\n" +
|
"\t" + LCM[0] + "," + LCM[3] + "," + LCM[6] + ",\n" +
|
||||||
"\t" + LCM[1] + "," + LCM[4] + "," + LCM[7] + ",\n" +
|
"\t" + LCM[1] + "," + LCM[4] + "," + LCM[7] + ",\n" +
|
||||||
"\t" + LCM[2] + "," + LCM[5] + "," + LCM[8] + "\n" )
|
"\t" + LCM[2] + "," + LCM[5] + "," + LCM[8] + "\n" )
|
||||||
f.write("\t};\n\n")
|
f.write("\t};\n\n")
|
||||||
|
|
||||||
|
## Meshes
|
||||||
|
|
||||||
actorPtr = first_mesh
|
actorPtr = first_mesh
|
||||||
levelPtr = first_mesh
|
levelPtr = first_mesh
|
||||||
propPtr = first_mesh
|
propPtr = first_mesh
|
||||||
@ -338,23 +538,24 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
|
|
||||||
for m in bpy.data.meshes:
|
for m in bpy.data.meshes:
|
||||||
|
|
||||||
# Write vertices vectors
|
# Store vertices coordinates by axis to find max/min coordinates
|
||||||
|
|
||||||
# AABB : Store vertices coordinates by axis
|
|
||||||
Xvals = []
|
Xvals = []
|
||||||
Yvals = []
|
Yvals = []
|
||||||
Zvals = []
|
Zvals = []
|
||||||
|
|
||||||
# remove '.' from mesh name
|
|
||||||
cleanName = CleanName(m.name)
|
cleanName = CleanName(m.name)
|
||||||
# ~ cleanName = m.name.replace('.','_')
|
|
||||||
# ~ cleanName = unicodedata.normalize('NFKD',cleanName).encode('ASCII', 'ignore').decode()
|
# Write vertices vectors
|
||||||
|
|
||||||
f.write("SVECTOR "+"model"+cleanName+"_mesh[] = {\n")
|
f.write("SVECTOR "+"model"+cleanName+"_mesh[] = {\n")
|
||||||
|
|
||||||
for i in range(len(m.vertices)):
|
for i in range(len(m.vertices)):
|
||||||
|
|
||||||
v = m.vertices[i].co
|
v = m.vertices[i].co
|
||||||
|
|
||||||
# AABB : append vertices coords by axis
|
# Append vertex coords to lists
|
||||||
|
|
||||||
Xvals.append(v.x)
|
Xvals.append(v.x)
|
||||||
Yvals.append(v.y)
|
Yvals.append(v.y)
|
||||||
Zvals.append(-v.z)
|
Zvals.append(-v.z)
|
||||||
@ -390,72 +591,124 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
|
|
||||||
|
|
||||||
if len(m.uv_textures) != None:
|
if len(m.uv_textures) != None:
|
||||||
|
|
||||||
for t in range(len(m.uv_textures)):
|
for t in range(len(m.uv_textures)):
|
||||||
|
|
||||||
if m.uv_textures[t].data[0].image != None:
|
if m.uv_textures[t].data[0].image != None:
|
||||||
|
|
||||||
f.write("SVECTOR "+"model"+cleanName+"_uv[] = {\n")
|
f.write("SVECTOR "+"model"+cleanName+"_uv[] = {\n")
|
||||||
|
|
||||||
texture_image = m.uv_textures[t].data[0].image
|
texture_image = m.uv_textures[t].data[0].image
|
||||||
|
|
||||||
tex_width = texture_image.size[0]
|
tex_width = texture_image.size[0]
|
||||||
|
|
||||||
tex_height = texture_image.size[1]
|
tex_height = texture_image.size[1]
|
||||||
|
|
||||||
uv_layer = m.uv_layers[0].data
|
uv_layer = m.uv_layers[0].data
|
||||||
|
|
||||||
for i in range(len(uv_layer)):
|
for i in range(len(uv_layer)):
|
||||||
|
|
||||||
u = uv_layer[i].uv
|
u = uv_layer[i].uv
|
||||||
|
|
||||||
ux = u.x * tex_width
|
ux = u.x * tex_width
|
||||||
|
|
||||||
uy = u.y * tex_height
|
uy = u.y * tex_height
|
||||||
|
|
||||||
# ~ if self.exp_Precalc and m.get('isBG'):
|
# ~ if self.exp_Precalc and m.get('isBG'):
|
||||||
# ~ f.write("\t255, 255, 0, 0") # Clamp values to 0-255 to avoid tpage overflow
|
# ~ f.write("\t255, 255, 0, 0") # Clamp values to 0-255 to avoid tpage overflow
|
||||||
# ~ else:
|
# ~ else:
|
||||||
|
|
||||||
f.write("\t"+str(max(0, min( round(ux) , 255 )))+","+str(max(0, min(round(tex_height - uy) , 255 )))+", 0, 0") # Clamp values to 0-255 to avoid tpage overflow
|
f.write("\t"+str(max(0, min( round(ux) , 255 )))+","+str(max(0, min(round(tex_height - uy) , 255 )))+", 0, 0") # Clamp values to 0-255 to avoid tpage overflow
|
||||||
|
|
||||||
if i != len(uv_layer) - 1:
|
if i != len(uv_layer) - 1:
|
||||||
|
|
||||||
f.write(",")
|
f.write(",")
|
||||||
|
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
f.write("};\n\n")
|
f.write("};\n\n")
|
||||||
|
|
||||||
# save uv tex if needed - still have to convert them to tim...
|
# Save UV texture to a file in ./TIM
|
||||||
|
# It will have to be converted to a tim file
|
||||||
|
|
||||||
if texture_image.filepath == '':
|
if texture_image.filepath == '':
|
||||||
|
|
||||||
os.makedirs(dirpath, exist_ok = 1)
|
os.makedirs(dirpath, exist_ok = 1)
|
||||||
|
|
||||||
texture_image.filepath_raw = folder + os.sep + "TIM" + os.sep + CleanName(texture_image.name) + "." + texture_image.file_format
|
texture_image.filepath_raw = folder + os.sep + "TIM" + os.sep + CleanName(texture_image.name) + "." + texture_image.file_format
|
||||||
|
|
||||||
texture_image.save()
|
texture_image.save()
|
||||||
|
|
||||||
# Write vertex colors vectors
|
# Write vertex colors vectors
|
||||||
|
|
||||||
f.write("CVECTOR "+"model"+cleanName+"_color[] = {\n")
|
f.write("CVECTOR "+"model"+cleanName+"_color[] = {\n")
|
||||||
|
|
||||||
# If vertex colors exist, use them
|
# If vertex colors exist, use them
|
||||||
|
|
||||||
if len(m.vertex_colors) != 0:
|
if len(m.vertex_colors) != 0:
|
||||||
|
|
||||||
colors = m.vertex_colors[0].data
|
colors = m.vertex_colors[0].data
|
||||||
|
|
||||||
for i in range(len(colors)):
|
for i in range(len(colors)):
|
||||||
|
|
||||||
f.write("\t"+str(int(colors[i].color.r*255))+","+str(int(colors[i].color.g*255))+","+str(int(colors[i].color.b*255))+", 0")
|
f.write("\t"+str(int(colors[i].color.r*255))+","+str(int(colors[i].color.g*255))+","+str(int(colors[i].color.b*255))+", 0")
|
||||||
|
|
||||||
if i != len(colors) - 1:
|
if i != len(colors) - 1:
|
||||||
|
|
||||||
f.write(",")
|
f.write(",")
|
||||||
|
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
# If no vertex colors, default to 2 whites, 1 grey
|
# If no vertex colors, default to 2 whites, 1 grey
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
for i in range(len(m.polygons) * 3):
|
for i in range(len(m.polygons) * 3):
|
||||||
|
|
||||||
if i % 3 == 0:
|
if i % 3 == 0:
|
||||||
f.write("\t80,80,80,0") # Let's add a bit more relief with a shade of grey
|
|
||||||
|
f.write("\t80,80,80,0")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
f.write("\t128,128,128,0")
|
f.write("\t128,128,128,0")
|
||||||
|
|
||||||
if i != (len(m.polygons) * 3) - 1:
|
if i != (len(m.polygons) * 3) - 1:
|
||||||
|
|
||||||
f.write(",")
|
f.write(",")
|
||||||
|
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
f.write("};\n\n")
|
f.write("};\n\n")
|
||||||
|
|
||||||
# Write polygons index + type
|
# Write polygons index + type
|
||||||
|
|
||||||
f.write("PRIM "+"model"+cleanName+"_index[] = {\n")
|
f.write("PRIM "+"model"+cleanName+"_index[] = {\n")
|
||||||
|
|
||||||
for i in range(len(m.polygons)):
|
for i in range(len(m.polygons)):
|
||||||
|
|
||||||
poly = m.polygons[i]
|
poly = m.polygons[i]
|
||||||
|
|
||||||
f.write("\t"+str(poly.vertices[0])+","+str(poly.vertices[1])+","+str(poly.vertices[2]))
|
f.write("\t"+str(poly.vertices[0])+","+str(poly.vertices[1])+","+str(poly.vertices[2]))
|
||||||
|
|
||||||
if len(poly.vertices) > 3:
|
if len(poly.vertices) > 3:
|
||||||
|
|
||||||
f.write("," + str(poly.vertices[3]) + ",8")
|
f.write("," + str(poly.vertices[3]) + ",8")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
f.write(",0,4")
|
f.write(",0,4")
|
||||||
|
|
||||||
if i != len(m.polygons) - 1:
|
if i != len(m.polygons) - 1:
|
||||||
|
|
||||||
f.write(",")
|
f.write(",")
|
||||||
|
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
f.write("};\n\n")
|
f.write("};\n\n")
|
||||||
|
|
||||||
# get custom properties isRigidBody, isPrism, isAnim
|
# Get object's custom properties
|
||||||
|
|
||||||
chkProp = {
|
chkProp = {
|
||||||
'isAnim':0,
|
'isAnim':0,
|
||||||
'isRigidBody':0,
|
'isRigidBody':0,
|
||||||
@ -488,16 +741,24 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
|
|
||||||
if m.get('isLevel'):
|
if m.get('isLevel'):
|
||||||
nodePtr = cleanName
|
nodePtr = cleanName
|
||||||
# write vertex anim if isAnim != 0 # https://stackoverflow.com/questions/9138637/vertex-animation-exporter-for-blender
|
|
||||||
|
## Vertex animation
|
||||||
|
|
||||||
|
# write vertex anim if isAnim != 0
|
||||||
|
# Source : https://stackoverflow.com/questions/9138637/vertex-animation-exporter-for-blender
|
||||||
|
|
||||||
if m.get("isAnim") is not None and m["isAnim"] != 0:
|
if m.get("isAnim") is not None and m["isAnim"] != 0:
|
||||||
|
|
||||||
#write vertex pos
|
# Write vertex pos
|
||||||
|
|
||||||
o = bpy.data.objects[m.name]
|
o = bpy.data.objects[m.name]
|
||||||
|
|
||||||
# ~ frame_start = bpy.context.scene.frame_start
|
# ~ frame_start = bpy.context.scene.frame_start
|
||||||
|
|
||||||
frame_start = int(bpy.data.actions[m.name].frame_range[0])
|
frame_start = int(bpy.data.actions[m.name].frame_range[0])
|
||||||
|
|
||||||
# ~ frame_end = bpy.context.scene.frame_end
|
# ~ frame_end = bpy.context.scene.frame_end
|
||||||
|
|
||||||
frame_end = int(bpy.data.actions[m.name].frame_range[1])
|
frame_end = int(bpy.data.actions[m.name].frame_range[1])
|
||||||
|
|
||||||
nFrame = frame_end - frame_start
|
nFrame = frame_end - frame_start
|
||||||
@ -509,11 +770,13 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
for i in range(frame_start, frame_end):
|
for i in range(frame_start, frame_end):
|
||||||
|
|
||||||
bpy.context.scene.frame_set(i)
|
bpy.context.scene.frame_set(i)
|
||||||
|
|
||||||
bpy.context.scene.update()
|
bpy.context.scene.update()
|
||||||
|
|
||||||
nm = o.to_mesh(bpy.context.scene, True, 'PREVIEW')
|
nm = o.to_mesh(bpy.context.scene, True, 'PREVIEW')
|
||||||
|
|
||||||
if i == 0 :
|
if i == 0 :
|
||||||
|
|
||||||
f.write("VANIM model"+cleanName+"_anim = {\n" +
|
f.write("VANIM model"+cleanName+"_anim = {\n" +
|
||||||
"\t" + str(nFrame) + ",\n" +
|
"\t" + str(nFrame) + ",\n" +
|
||||||
"\t" + str(len(nm.vertices)) + ",\n" +
|
"\t" + str(len(nm.vertices)) + ",\n" +
|
||||||
@ -523,28 +786,41 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
"\t" + str(chkProp['lerp']) + ",\n" +
|
"\t" + str(chkProp['lerp']) + ",\n" +
|
||||||
"\t{\n"
|
"\t{\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
for v in range(len(nm.vertices)):
|
for v in range(len(nm.vertices)):
|
||||||
|
|
||||||
if v == 0:
|
if v == 0:
|
||||||
# ~ f.write("{\n")
|
|
||||||
f.write("\t\t//Frame %d\n" % i)
|
f.write("\t\t//Frame %d\n" % i)
|
||||||
|
|
||||||
f.write("\t\t{ " + str(round(nm.vertices[v].co.x*scale)) + "," + str(round(-nm.vertices[v].co.z*scale)) + "," + str(round(nm.vertices[v].co.y*scale)) + " }")
|
f.write("\t\t{ " + str(round(nm.vertices[v].co.x*scale)) + "," + str(round(-nm.vertices[v].co.z*scale)) + "," + str(round(nm.vertices[v].co.y*scale)) + " }")
|
||||||
|
|
||||||
if c != len(nm.vertices) * (nFrame) * 3 - 3:
|
if c != len(nm.vertices) * (nFrame) * 3 - 3:
|
||||||
|
|
||||||
f.write(",\n")
|
f.write(",\n")
|
||||||
|
|
||||||
if v == len(nm.vertices) - 1:
|
if v == len(nm.vertices) - 1:
|
||||||
|
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
c += 3;
|
c += 3;
|
||||||
# ~ if i != (frame_end - frame_start):
|
|
||||||
# ~ f.write(",")
|
|
||||||
tmp_meshes.append(nm)
|
tmp_meshes.append(nm)
|
||||||
# ~ tmp_meshes.remove(nm)
|
|
||||||
f.write("\n\t}\n};\n")
|
f.write("\n\t}\n};\n")
|
||||||
|
|
||||||
|
# Remove meshe's working copies
|
||||||
|
|
||||||
for nm in tmp_meshes:
|
for nm in tmp_meshes:
|
||||||
|
|
||||||
bpy.data.meshes.remove(nm)
|
bpy.data.meshes.remove(nm)
|
||||||
|
|
||||||
#Stuff # ~ bpy.data.objects[bpy.data.meshes[0].name].active_shape_key.value : access shape_key
|
# bpy.data.objects[bpy.data.meshes[0].name].active_shape_key.value : access shape_key
|
||||||
|
|
||||||
|
## Mesh world transform setup
|
||||||
|
|
||||||
|
# Write object matrix, rot and pos vectors
|
||||||
|
|
||||||
#write object matrix, rot and pos vectors
|
|
||||||
f.write("MATRIX model"+cleanName+"_matrix = {0};\n" +
|
f.write("MATRIX model"+cleanName+"_matrix = {0};\n" +
|
||||||
"VECTOR model"+cleanName+"_pos = {"+ str(round(bpy.data.objects[m.name].location.x * scale)) + "," + str(round(-bpy.data.objects[m.name].location.z * scale)) + "," + str(round(bpy.data.objects[m.name].location.y * scale)) + ", 0};\n" +
|
"VECTOR model"+cleanName+"_pos = {"+ str(round(bpy.data.objects[m.name].location.x * scale)) + "," + str(round(-bpy.data.objects[m.name].location.z * scale)) + "," + str(round(bpy.data.objects[m.name].location.y * scale)) + ", 0};\n" +
|
||||||
"SVECTOR model"+cleanName+"_rot = {"+ str(round(degrees(bpy.data.objects[m.name].rotation_euler.x)/360 * 4096)) + "," + str(round(degrees(-bpy.data.objects[m.name].rotation_euler.z)/360 * 4096)) + "," + str(round(degrees(bpy.data.objects[m.name].rotation_euler.y)/360 * 4096)) + "};\n" +
|
"SVECTOR model"+cleanName+"_rot = {"+ str(round(degrees(bpy.data.objects[m.name].rotation_euler.x)/360 * 4096)) + "," + str(round(degrees(-bpy.data.objects[m.name].rotation_euler.z)/360 * 4096)) + "," + str(round(degrees(bpy.data.objects[m.name].rotation_euler.y)/360 * 4096)) + "};\n" +
|
||||||
@ -570,67 +846,102 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
"\t};\n\n")
|
"\t};\n\n")
|
||||||
|
|
||||||
# Write TMESH struct
|
# Write TMESH struct
|
||||||
|
|
||||||
f.write("TMESH "+"model"+cleanName+" = {\n")
|
f.write("TMESH "+"model"+cleanName+" = {\n")
|
||||||
|
|
||||||
f.write("\t"+"model"+cleanName+"_mesh, \n")
|
f.write("\t"+"model"+cleanName+"_mesh, \n")
|
||||||
|
|
||||||
f.write("\t"+"model"+cleanName+"_normal,\n")
|
f.write("\t"+"model"+cleanName+"_normal,\n")
|
||||||
|
|
||||||
if len(m.uv_textures) != None:
|
if len(m.uv_textures) != None:
|
||||||
|
|
||||||
for t in range(len(m.uv_textures)):
|
for t in range(len(m.uv_textures)):
|
||||||
|
|
||||||
if m.uv_textures[0].data[0].image != None:
|
if m.uv_textures[0].data[0].image != None:
|
||||||
|
|
||||||
f.write("\t"+"model"+cleanName+"_uv,\n")
|
f.write("\t"+"model"+cleanName+"_uv,\n")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
f.write("\t0,\n")
|
f.write("\t0,\n")
|
||||||
else:
|
else:
|
||||||
|
|
||||||
f.write("\t0,\n")
|
f.write("\t0,\n")
|
||||||
|
|
||||||
f.write("\t"+"model"+cleanName+"_color, \n")
|
f.write("\t"+"model"+cleanName+"_color, \n")
|
||||||
|
|
||||||
# According to libgte.h, TMESH.len should be # of vertices. Meh...
|
# According to libgte.h, TMESH.len should be # of vertices. Meh...
|
||||||
|
|
||||||
f.write("\t"+str(len(m.polygons))+"\n")
|
f.write("\t"+str(len(m.polygons))+"\n")
|
||||||
|
|
||||||
f.write("};\n\n")
|
f.write("};\n\n")
|
||||||
|
|
||||||
# write texture binary name and declare TIM_IMAGE
|
# Write texture binary name and declare TIM_IMAGE
|
||||||
# by default, load the file from the TIM folder
|
# By default, loads the file from the ./TIM folder
|
||||||
# ~ if len(m.uv_textures) != 0:
|
|
||||||
|
|
||||||
if len(m.uv_textures) != None:
|
if len(m.uv_textures) != None:
|
||||||
|
|
||||||
for t in range(len(m.uv_textures)):
|
for t in range(len(m.uv_textures)):
|
||||||
|
|
||||||
if m.uv_textures[0].data[0].image != None:
|
if m.uv_textures[0].data[0].image != None:
|
||||||
|
|
||||||
tex_name = texture_image.name
|
tex_name = texture_image.name
|
||||||
|
|
||||||
prefix = str.partition(tex_name, ".")[0].replace('-','_')
|
prefix = str.partition(tex_name, ".")[0].replace('-','_')
|
||||||
|
|
||||||
prefix = CleanName(prefix)
|
prefix = CleanName(prefix)
|
||||||
# add Tex name to array if !exist
|
|
||||||
|
# Add Tex name to list if it's not in there already
|
||||||
|
|
||||||
if prefix in timList:
|
if prefix in timList:
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_start[];\n")
|
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_start[];\n")
|
||||||
|
|
||||||
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_end[];\n")
|
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_end[];\n")
|
||||||
|
|
||||||
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_length;\n\n")
|
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_length;\n\n")
|
||||||
|
|
||||||
f.write("TIM_IMAGE tim_" + prefix + ";\n\n")
|
f.write("TIM_IMAGE tim_" + prefix + ";\n\n")
|
||||||
|
|
||||||
timList.append(prefix)
|
timList.append(prefix)
|
||||||
|
|
||||||
f.write("MESH mesh"+cleanName+" = {\n")
|
f.write("MESH mesh"+cleanName+" = {\n")
|
||||||
|
|
||||||
f.write("\t&model"+ cleanName +",\n")
|
f.write("\t&model"+ cleanName +",\n")
|
||||||
|
|
||||||
f.write("\tmodel" + cleanName + "_index,\n")
|
f.write("\tmodel" + cleanName + "_index,\n")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if len(m.uv_textures) != None:
|
if len(m.uv_textures) != None:
|
||||||
|
|
||||||
for t in range(len(m.uv_textures)):
|
for t in range(len(m.uv_textures)):
|
||||||
|
|
||||||
if m.uv_textures[0].data[0].image != None:
|
if m.uv_textures[0].data[0].image != None:
|
||||||
|
|
||||||
tex_name = texture_image.name
|
tex_name = texture_image.name
|
||||||
|
|
||||||
prefix = str.partition(tex_name, ".")[0].replace('-','_')
|
prefix = str.partition(tex_name, ".")[0].replace('-','_')
|
||||||
|
|
||||||
prefix = CleanName(prefix)
|
prefix = CleanName(prefix)
|
||||||
|
|
||||||
f.write("\t&tim_"+ prefix + ",\n")
|
f.write("\t&tim_"+ prefix + ",\n")
|
||||||
|
|
||||||
f.write("\t_binary_TIM_" + prefix + "_tim_start,\n")
|
f.write("\t_binary_TIM_" + prefix + "_tim_start,\n")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
f.write("\t0,\n" +
|
f.write("\t0,\n" +
|
||||||
|
|
||||||
"\t0,\n")
|
"\t0,\n")
|
||||||
else:
|
else:
|
||||||
|
|
||||||
f.write("\t0,\n" +
|
f.write("\t0,\n" +
|
||||||
|
|
||||||
"\t0,\n")
|
"\t0,\n")
|
||||||
|
|
||||||
f.write("\t&model"+cleanName+"_matrix,\n" +
|
f.write("\t&model"+cleanName+"_matrix,\n" +
|
||||||
@ -646,83 +957,115 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
|||||||
"\t&model"+cleanName+"_p,\n" +
|
"\t&model"+cleanName+"_p,\n" +
|
||||||
"\t&model"+cleanName+"_OTz,\n" +
|
"\t&model"+cleanName+"_OTz,\n" +
|
||||||
"\t&model"+cleanName+"_body")
|
"\t&model"+cleanName+"_body")
|
||||||
|
|
||||||
if m.get("isAnim") is not None and m["isAnim"] != 0:
|
if m.get("isAnim") is not None and m["isAnim"] != 0:
|
||||||
|
|
||||||
f.write(",\n\t&model"+cleanName+"_anim\n")
|
f.write(",\n\t&model"+cleanName+"_anim\n")
|
||||||
else:
|
else:
|
||||||
|
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
f.write("};\n\n")
|
f.write("};\n\n")
|
||||||
|
|
||||||
f.write("MESH * meshes[" + str(len(bpy.data.meshes)) + "] = {\n")
|
f.write("MESH * meshes[" + str(len(bpy.data.meshes)) + "] = {\n")
|
||||||
|
|
||||||
for k in range(len(bpy.data.meshes)):
|
for k in range(len(bpy.data.meshes)):
|
||||||
|
|
||||||
cleanName = CleanName(bpy.data.meshes[k].name)
|
cleanName = CleanName(bpy.data.meshes[k].name)
|
||||||
|
|
||||||
f.write("\t&mesh" + cleanName)
|
f.write("\t&mesh" + cleanName)
|
||||||
|
|
||||||
if k != len(bpy.data.meshes) - 1:
|
if k != len(bpy.data.meshes) - 1:
|
||||||
|
|
||||||
f.write(",\n")
|
f.write(",\n")
|
||||||
|
|
||||||
f.write("\n}; \n")
|
f.write("\n}; \n")
|
||||||
|
|
||||||
# nothing in camAngles, use default camera
|
# If camAngles is empty, use default camera, and do not include pre-calculated backgrounds
|
||||||
|
|
||||||
if not camAngles:
|
if not camAngles:
|
||||||
|
|
||||||
f.write("CAMANGLE camAngle_" + CleanName(defaultCam) + " = {\n" +
|
f.write("CAMANGLE camAngle_" + CleanName(defaultCam) + " = {\n" +
|
||||||
"\t&camPos_" + CleanName(defaultCam) + ",\n" +
|
"\t&camPos_" + CleanName(defaultCam) + ",\n" +
|
||||||
"\t0,\n" +
|
"\t0,\n" +
|
||||||
"\t0\n" +
|
"\t0\n" +
|
||||||
"};\n\n")
|
"};\n\n")
|
||||||
|
|
||||||
# cam angles is populated
|
# If camAngles is populated, use backgrounds and camera angles
|
||||||
|
|
||||||
for o in camAngles:
|
for o in camAngles:
|
||||||
|
|
||||||
prefix = CleanName(o.name)
|
prefix = CleanName(o.name)
|
||||||
|
|
||||||
# include Tim data
|
# Include Tim data
|
||||||
|
|
||||||
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_start[];\n")
|
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_start[];\n")
|
||||||
|
|
||||||
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_end[];\n")
|
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_end[];\n")
|
||||||
|
|
||||||
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_length;\n\n")
|
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_length;\n\n")
|
||||||
|
|
||||||
# write corresponding TIM_IMAGE struct
|
# Write corresponding TIM_IMAGE struct
|
||||||
|
|
||||||
f.write("TIM_IMAGE tim_bg_" + prefix + ";\n\n")
|
f.write("TIM_IMAGE tim_bg_" + prefix + ";\n\n")
|
||||||
|
|
||||||
# write corresponding CamAngle struct
|
# Write corresponding CamAngle struct
|
||||||
|
|
||||||
f.write("CAMANGLE camAngle_" + prefix + " = {\n" +
|
f.write("CAMANGLE camAngle_" + prefix + " = {\n" +
|
||||||
"\t&camPos_" + prefix + ",\n" +
|
"\t&camPos_" + prefix + ",\n" +
|
||||||
"\t&tim_bg_" + prefix + ",\n" +
|
"\t&tim_bg_" + prefix + ",\n" +
|
||||||
"\t_binary_TIM_bg_" + prefix + "_tim_start\n" +
|
"\t_binary_TIM_bg_" + prefix + "_tim_start\n" +
|
||||||
"};\n\n")
|
"};\n\n")
|
||||||
|
|
||||||
# write cam angles array for loops
|
# Write camera angles in an array for loops
|
||||||
|
|
||||||
f.write("CAMANGLE * camAngles[" + str(len(camAngles)) + "] = {\n")
|
f.write("CAMANGLE * camAngles[" + str(len(camAngles)) + "] = {\n")
|
||||||
|
|
||||||
for o in camAngles:
|
for o in camAngles:
|
||||||
|
|
||||||
prefix = CleanName(o.name)
|
prefix = CleanName(o.name)
|
||||||
|
|
||||||
f.write("\t&camAngle_" + prefix + ",\n")
|
f.write("\t&camAngle_" + prefix + ",\n")
|
||||||
|
|
||||||
f.write("};\n\n")
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
|
||||||
f.write("MESH * actorPtr = &mesh" + actorPtr + ";\n")
|
f.write("MESH * actorPtr = &mesh" + actorPtr + ";\n")
|
||||||
|
|
||||||
f.write("MESH * levelPtr = &mesh" + levelPtr + ";\n")
|
f.write("MESH * levelPtr = &mesh" + levelPtr + ";\n")
|
||||||
|
|
||||||
f.write("MESH * propPtr = &mesh" + propPtr + ";\n\n")
|
f.write("MESH * propPtr = &mesh" + propPtr + ";\n\n")
|
||||||
|
|
||||||
f.write("CAMANGLE * camPtr = &camAngle_" + CleanName(defaultCam) + ";\n\n")
|
f.write("CAMANGLE * camPtr = &camAngle_" + CleanName(defaultCam) + ";\n\n")
|
||||||
|
|
||||||
f.write("NODE * curNode = &node_" + nodePtr + ";\n\n")
|
f.write("NODE * curNode = &node" + nodePtr + ";\n\n")
|
||||||
|
|
||||||
|
# Set default camera back in Blender
|
||||||
|
|
||||||
# set default cam back
|
|
||||||
if defaultCam != 'NULL':
|
if defaultCam != 'NULL':
|
||||||
|
|
||||||
bpy.context.scene.camera = bpy.data.objects[defaultCam]
|
bpy.context.scene.camera = bpy.data.objects[defaultCam]
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
return {'FINISHED'};
|
return {'FINISHED'};
|
||||||
|
|
||||||
def menu_func(self, context):
|
def menu_func(self, context):
|
||||||
|
|
||||||
self.layout.operator(ExportMyFormat.bl_idname, text="PSX Format(.c)");
|
self.layout.operator(ExportMyFormat.bl_idname, text="PSX Format(.c)");
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
|
||||||
bpy.utils.register_module(__name__);
|
bpy.utils.register_module(__name__);
|
||||||
|
|
||||||
bpy.types.INFO_MT_file_export.append(menu_func);
|
bpy.types.INFO_MT_file_export.append(menu_func);
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
|
|
||||||
bpy.utils.unregister_module(__name__);
|
bpy.utils.unregister_module(__name__);
|
||||||
|
|
||||||
bpy.types.INFO_MT_file_export.remove(menu_func);
|
bpy.types.INFO_MT_file_export.remove(menu_func);
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
register()
|
register()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user