From de5d710b87879d6a0b06407da096ec505f8b7679 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 17 Aug 2014 17:43:41 +0300 Subject: [PATCH] Add a Loader for Scene, and a matching Blender exporter --- blender/io_mspgl/__init__.py | 22 ++++++++++-- blender/io_mspgl/export_mesh.py | 7 ++-- blender/io_mspgl/export_object.py | 11 +++--- blender/io_mspgl/export_scene.py | 57 +++++++++++++++++++++++++++++++ source/animatedobject.cpp | 30 ++++++++++++++++ source/animatedobject.h | 14 ++++++++ source/scene.cpp | 23 +++++++++++++ source/scene.h | 17 ++++++++- 8 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 blender/io_mspgl/export_scene.py diff --git a/blender/io_mspgl/__init__.py b/blender/io_mspgl/__init__.py index 1e085baf..b7e14fda 100644 --- a/blender/io_mspgl/__init__.py +++ b/blender/io_mspgl/__init__.py @@ -7,7 +7,7 @@ bl_info = { if "bpy" in locals(): import imp - for sub in "armature", "export_armature", "export_mesh", "export_object", "mesh", "outfile", "properties", "util": + for sub in "armature", "export_armature", "export_mesh", "export_object", "export_scene", "mesh", "outfile", "properties", "util": if sub in locals(): imp.reload(locals()[sub]) @@ -96,7 +96,7 @@ class ExportMspGLObject(bpy.types.Operator, ExportMspGLMeshBase): filename_ext = ".object" - external_tech = bpy.props.BoolProperty(name="External technique", description="Use an external technique specified in the object", default=True) + external_tech = bpy.props.BoolProperty(name="External technique", description="Use an external technique specified in the object's properties", default=True) textures = bpy.props.EnumProperty(name="Textures", description="Export textures", default="REF", items=(("NONE", "None", "Ignore textures"), @@ -143,10 +143,28 @@ class ExportMspGLArmature(bpy.types.Operator, ExportMspGLBase): from .export_armature import ArmatureExporter return ArmatureExporter() +class ExportMspGLScene(bpy.types.Operator, ExportMspGLBase): + bl_idname = "export.mspgl_scene" + bl_label = "Export Msp GL scene" + + filename_ext = ".scene" + + external_tech = bpy.props.BoolProperty(name="External techniques", description="Use external techniques specified in objects' properties", default=True) + resource_collection = bpy.props.BoolProperty(name="Resource collection", description="Put resources to a single collection file", default=True) + + def create_exporter(self): + from .export_scene import SceneExporter + return SceneExporter() + + def draw(self, context): + col = self.layout.column() + col.prop(self, "resource_collection") + def menu_func_export(self, context): self.layout.operator(ExportMspGLMesh.bl_idname, text="Msp GL mesh") self.layout.operator(ExportMspGLObject.bl_idname, text="Msp GL object") self.layout.operator(ExportMspGLArmature.bl_idname, text="Msp GL armature") + self.layout.operator(ExportMspGLScene.bl_idname, text="Msp GL scene") from .properties import MspGLProperties diff --git a/blender/io_mspgl/export_mesh.py b/blender/io_mspgl/export_mesh.py index dbb3a269..e429d7ae 100644 --- a/blender/io_mspgl/export_mesh.py +++ b/blender/io_mspgl/export_mesh.py @@ -191,9 +191,10 @@ class MeshExporter: return strips, loose - def export(self, context, out_file): + def export(self, context, out_file, objs=None): if self.compound: - objs = context.selected_objects + if objs is None: + objs = context.selected_objects check = objs while check: children = [] @@ -203,7 +204,7 @@ class MeshExporter: children.append(c) objs += children check = children - else: + elif objs is None: objs = [context.active_object] if not objs: diff --git a/blender/io_mspgl/export_object.py b/blender/io_mspgl/export_object.py index aad1c087..d89afd05 100644 --- a/blender/io_mspgl/export_object.py +++ b/blender/io_mspgl/export_object.py @@ -17,8 +17,11 @@ class ObjectExporter: self.external_tech = True self.shared_tech = True - def export(self, context, out_file): - obj = context.active_object + def export(self, context, out_file, objs=None): + if objs is None: + obj = context.active_object + else: + obj = objs[0] from .outfile import open_output out_file = open_output(out_file) @@ -32,11 +35,11 @@ class ObjectExporter: path, base = os.path.split(out_file.filename) base, ext = os.path.splitext(base) mesh_out = open_output(os.path.join(path, base+".mesh")) - mesh = mesh_export.export(context, mesh_out) + mesh = mesh_export.export(context, mesh_out, objs) out_file.write("mesh", '"{}.mesh"'.format(base)) else: out_file.begin("mesh") - mesh = mesh_export.export(context, out_file) + mesh = mesh_export.export(context, out_file, objs) out_file.end() if self.external_tech and obj.technique: diff --git a/blender/io_mspgl/export_scene.py b/blender/io_mspgl/export_scene.py new file mode 100644 index 00000000..8f224fea --- /dev/null +++ b/blender/io_mspgl/export_scene.py @@ -0,0 +1,57 @@ +import math +import os +from .export_object import ObjectExporter +from .outfile import OutFile + +class SceneExporter: + def __init__(self): + self.external_tech = True + self.resource_collection = True + + def export(self, context, out_file): + objs = context.selected_objects + objs = [o for o in objs if o.type=="MESH" and (not o.compound or o.parent not in objs)] + + from .outfile import open_output + out_file = open_output(out_file) + + path, base = os.path.split(out_file.filename) + base, ext = os.path.splitext(base) + + object_export = ObjectExporter() + object_export.compound = True + object_export.external_tech = self.external_tech + + if self.resource_collection: + res_out = open_output(os.path.join(path, base+"_resources.mdc")) + + # TODO Export techniques as separate items in the collection + for o in objs: + res_out.begin("object", '"{}.object"'.format(o.name)) + object_export.export(context, res_out, [o]) + res_out.end() + else: + object_export.separate_tech = True + res_dir = os.path.join(path, base+"_resources") + if not os.path.exists(res_dir): + os.makedirs(res_dir) + for o in objs: + obj_out = open_output(os.path.join(res_dir, o.name+".object")) + object_export.export(context, obj_out, [o]) + + for o in objs: + out_file.begin("object", '"{}.object"'.format(o.name)) + # XXX Parent relationships screw up the location and rotation + out_file.write("position", o.location[0], o.location[1], o.location[2]) + if o.rotation_mode=="AXIS_ANGLE": + angle = o.rotation_axis_angle[0] + axis = o.rotation_axis_angle[1:] + else: + if o.rotation_mode=="QUATERNION": + q = o.rotation_quaternion + else: + q = o.rotation_euler.to_quaternion() + angle = q.angle + axis = q.axis + out_file.write("rotation", angle*180/math.pi, axis[0], axis[1], axis[2]) + out_file.end(); diff --git a/source/animatedobject.cpp b/source/animatedobject.cpp index 63a25112..4be198a8 100644 --- a/source/animatedobject.cpp +++ b/source/animatedobject.cpp @@ -48,5 +48,35 @@ void AnimatedObject::setup_render(Renderer &renderer, const Tag &) const renderer.add_shader_data(*shdata); } + +AnimatedObject::Loader::Loader(AnimatedObject &o): + DataFile::ObjectLoader(o) +{ + add("position", &Loader::position); + add("rotation", &Loader::rotation); + add("scale", &Loader::scale); + add("scale", &Loader::scale_uniform); +} + +void AnimatedObject::Loader::position(float x, float y, float z) +{ + obj.matrix.translate(x, y, z); +} + +void AnimatedObject::Loader::rotation(float a, float x, float y, float z) +{ + obj.matrix.rotate_deg(a, x, y, z); +} + +void AnimatedObject::Loader::scale(float x, float y, float z) +{ + obj.matrix.scale(x, y, z); +} + +void AnimatedObject::Loader::scale_uniform(float s) +{ + obj.matrix.scale(s); +} + } // namespace GL } // namespace Msp diff --git a/source/animatedobject.h b/source/animatedobject.h index 6bcd37ce..4782951d 100644 --- a/source/animatedobject.h +++ b/source/animatedobject.h @@ -2,6 +2,7 @@ #define MSP_GL_ANIMATEDOBJECT_H_ #include +#include #include "matrix.h" #include "objectinstance.h" @@ -14,6 +15,19 @@ useful for displaying objects at a static position. */ class AnimatedObject: public ObjectInstance { +public: + class Loader: public DataFile::ObjectLoader + { + public: + Loader(AnimatedObject &); + + private: + void position(float, float, float); + void rotation(float, float, float, float); + void scale(float, float, float); + void scale_uniform(float); + }; + private: Matrix matrix; std::vector pose_data; diff --git a/source/scene.cpp b/source/scene.cpp index 3f0261f4..f233a09b 100644 --- a/source/scene.cpp +++ b/source/scene.cpp @@ -1,3 +1,5 @@ +#include +#include "animatedobject.h" #include "culler.h" #include "renderer.h" #include "scene.h" @@ -7,6 +9,12 @@ using namespace std; namespace Msp { namespace GL { +Scene::~Scene() +{ + for(list::iterator i=owned_data.begin(); i!=owned_data.end(); ++i) + delete *i; +} + void Scene::add_culler(Culler &c) { cullers.push_back(&c); @@ -39,5 +47,20 @@ bool Scene::cull(const Renderer &renderer, const Renderable &renderable) const return false; } + +Scene::Loader::Loader(Scene &s, Collection &c): + DataFile::CollectionObjectLoader(s, &c) +{ + add("object", &Loader::object); +} + +void Scene::Loader::object(const string &n) +{ + RefPtr anob = new AnimatedObject(get_collection().get(n)); + load_sub(*anob); + obj.add(*anob); + obj.owned_data.push_back(anob.release()); +} + } // namespace GL } // namespace Msp diff --git a/source/scene.h b/source/scene.h index 10b1ab65..687c581f 100644 --- a/source/scene.h +++ b/source/scene.h @@ -2,6 +2,7 @@ #define MSP_GL_SCENE_H_ #include +#include #include "renderable.h" namespace Msp { @@ -16,12 +17,26 @@ InstancedScene and OrderedScene. */ class Scene: public Renderable { +public: + class Loader: public DataFile::CollectionObjectLoader + { + public: + Loader(Scene &, Collection &); + + private: + void object(const std::string &); + }; + protected: + std::list owned_data; std::list cullers; Scene() { } +private: + Scene(const Scene &); + Scene &operator=(const Scene &); public: - virtual ~Scene() { } + virtual ~Scene(); virtual void add(const Renderable &) = 0; virtual void remove(const Renderable &) = 0; -- 2.43.0