[Bf-blender-cvs] [e9e08a1] master: Game Engine: Level of detail support and tools

Daniel Stokes noreply at git.blender.org
Wed Dec 18 02:05:04 CET 2013


Commit: e9e08a1d12594eab0e341049fc252ff8578e9333
Author: Daniel Stokes
Date:   Tue Dec 17 14:42:47 2013 -0800
http://developer.blender.org/rBe9e08a1d12594eab0e341049fc252ff8578e9333

Game Engine: Level of detail support and tools

Levels of detail can be added and modified in the object panel. The object
panel also contains new tools for generating levels of detail, setting up
levels of detail based on object names (useful for importing), and
clearing an object's level of detail settings. This is meant as a game
engine feature, though the level of details settings can be previewed in
the viewport.

Reviewed By: moguri, nexyon, brecht

Differential Revision: http://developer.blender.org/D109

===================================================================

M	release/scripts/startup/bl_operators/object.py
M	release/scripts/startup/bl_ui/properties_object.py
M	source/blender/blenkernel/BKE_object.h
M	source/blender/blenkernel/intern/material.c
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/editors/object/CMakeLists.txt
M	source/blender/editors/object/object_intern.h
A	source/blender/editors/object/object_lod.c
M	source/blender/editors/object/object_ops.c
M	source/blender/editors/space_view3d/drawobject.c
M	source/blender/editors/space_view3d/space_view3d.c
M	source/blender/editors/space_view3d/view3d_draw.c
M	source/blender/gpu/intern/gpu_draw.c
M	source/blender/makesdna/DNA_object_types.h
M	source/blender/makesrna/intern/rna_object.c
M	source/blender/windowmanager/WM_types.h
M	source/gameengine/Converter/BL_BlenderDataConversion.cpp
M	source/gameengine/Ketsji/KX_Dome.cpp
M	source/gameengine/Ketsji/KX_GameObject.cpp
M	source/gameengine/Ketsji/KX_GameObject.h
M	source/gameengine/Ketsji/KX_KetsjiEngine.cpp
M	source/gameengine/Ketsji/KX_Scene.cpp
M	source/gameengine/Ketsji/KX_Scene.h

===================================================================

diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index e5e53d6..3218af0 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -775,3 +775,154 @@ class DupliOffsetFromCursor(Operator):
         ob.users_group[group].dupli_offset = scene.cursor_location
 
         return {'FINISHED'}
+
+
+class LodByName(Operator):
+    """Add levels of detail to this object based on object names"""
+    bl_idname = "object.lod_by_name"
+    bl_label = "Setup Levels of Detail By Name"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.active_object is not None)
+
+    def execute(self, context):
+        scene = context.scene
+        ob = context.active_object
+        
+        prefix = ""
+        suffix = ""
+        name = ""
+        if ob.name.lower().startswith("lod0"):
+            prefix = ob.name[:4]
+            name = ob.name[4:]
+        elif ob.name.lower().endswith("lod0"):
+            name = ob.name[:-4]
+            suffix = ob.name[-4:]
+        else:
+            return {'CANCELLED'}
+
+        level = 0
+        while True:
+            level += 1
+
+            if prefix:
+                prefix = prefix[:3] + str(level)
+            if suffix:
+                suffix = suffix[:3] + str(level)
+
+            lod = None
+            try:
+                lod = bpy.data.objects[prefix + name + suffix]
+            except KeyError:
+                break
+
+            try:
+                ob.lod_levels[level]
+            except IndexError:
+                bpy.ops.object.lod_add()
+
+            ob.lod_levels[level].object = lod
+
+        return {'FINISHED'}
+
+
+class LodClearAll(Operator):
+    """Remove all levels of detail from this object"""
+    bl_idname = "object.lod_clear_all"
+    bl_label = "Clear All Levels of Detail"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.active_object is not None)
+
+    def execute(self, context):
+        scene = context.scene
+        ob = context.active_object
+
+        if ob.lod_levels:
+            while 'CANCELLED' not in bpy.ops.object.lod_remove():
+                pass
+
+        return {'FINISHED'}
+
+
+class LodGenerate(Operator):
+    """Generates levels of detail using the decimate modifier"""
+    bl_idname = "object.lod_generate"
+    bl_label = "Generate Levels of Detail"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    count = bpy.props.IntProperty(name="Count", default=3)
+    target = bpy.props.FloatProperty(name="Target Size", default=0.1,
+                                        min=0.0, max=1.0)
+    package = bpy.props.BoolProperty(name="Package into Group", default=False)
+    
+    @classmethod
+    def poll(cls, context):
+        return (context.active_object is not None)
+
+    def execute(self, context):
+        scene = bpy.context.scene
+        ob = scene.objects.active
+
+        lod_name = ob.name
+        lod_suffix = "lod"
+        lod_prefix = ""
+        if lod_name.lower().endswith("lod0"):
+            lod_suffix = lod_name[-3:-1]
+            lod_name = lod_name[:-3]
+        elif lod_name.lower().startswith("lod0"):
+            lod_suffix = ""
+            lod_prefix = lod_name[:3]
+            lod_name = lod_name[4:]
+
+        group_name = lod_name.strip(' ._')
+        if self.package:
+            try:
+                bpy.ops.object.group_link(group=group_name)
+            except TypeError:
+                bpy.ops.group.create(name=group_name)
+
+        step = (1.0 - self.target) / (self.count - 1)
+        for i in range(1, self.count):
+            scene.objects.active = ob
+            bpy.ops.object.duplicate()
+            lod = bpy.context.selected_objects[0]
+
+            scene.objects.active = ob
+            bpy.ops.object.lod_add()
+            scene.objects.active = lod
+
+            if lod_prefix:
+                lod.name = lod_prefix + str(i) + lod_name
+            else:
+                lod.name = lod_name + lod_suffix  + str(i)
+
+            lod.location.y = ob.location.y + 3.0 * i
+
+            if i == 1:
+                modifier = lod.modifiers.new("lod_decimate", "DECIMATE")
+            else:
+                modifier = lod.modifiers[-1]
+                
+            modifier.ratio = 1.0 - step*(i)
+
+            ob.lod_levels[i].object = lod
+
+            if self.package:
+                bpy.ops.object.group_link(group=group_name)
+                lod.parent = ob
+
+        if self.package:
+            for level in ob.lod_levels[1:]:
+                level.object.hide = level.object.hide_render = True
+
+        lod.select = False
+        ob.select = True
+        scene.objects.active = ob
+
+        return {'FINISHED'}
+
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index cbebdaf..dcd32b1 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -18,7 +18,7 @@
 
 # <pep8 compliant>
 import bpy
-from bpy.types import Panel
+from bpy.types import Menu, Panel
 from rna_prop_ui import PropertyPanel
 
 
@@ -125,6 +125,49 @@ class OBJECT_PT_transform_locks(ObjectButtonsPanel, Panel):
             sub.prop(ob, "lock_rotation_w", text="W")
 
 
+class OBJECT_MT_lod_tools(Menu):
+    bl_label = "Level Of Detail Tools"
+
+    def draw(self, context):
+        layout = self.layout
+        
+        layout.operator("object.lod_by_name", text="Set By Name")
+        layout.operator("object.lod_generate", text="Generate")
+        layout.operator("object.lod_clear_all", text="Clear All", icon='PANEL_CLOSE')
+
+
+class OBJECT_PT_levels_of_detail(ObjectButtonsPanel, Panel):
+    bl_label = "Levels of Detail"
+    COMPAT_ENGINES = {'BLENDER_GAME'}
+
+    @classmethod
+    def poll(cls, context):
+        return context.scene.render.engine in cls.COMPAT_ENGINES
+
+    def draw(self, context):
+        layout = self.layout
+        ob = context.object
+
+        col = layout.column()
+
+        for i, level in enumerate(ob.lod_levels):
+            if i == 0: continue
+            box = col.box()
+            row = box.row()
+            row.prop(level, "object", text="")
+            row.operator("object.lod_remove", text="", icon='PANEL_CLOSE').index = i
+
+            row = box.row()
+            row.prop(level, "distance")
+            row = row.row(align=True)
+            row.prop(level, "use_mesh", text="")
+            row.prop(level, "use_material", text="")
+
+        row = col.row(align=True)
+        row.operator("object.lod_add", text="Add", icon='ZOOMIN')
+        row.menu("OBJECT_MT_lod_tools", text="", icon='TRIA_DOWN')
+
+
 class OBJECT_PT_relations(ObjectButtonsPanel, Panel):
     bl_label = "Relations"
 
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 4341756..e6e6d62 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -87,6 +87,14 @@ struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const ch
 struct Object *BKE_object_add(struct Main *bmain, struct Scene *scene, int type);
 void *BKE_object_obdata_add_from_type(struct Main *bmain, int type);
 
+void BKE_object_lod_add(struct Object *ob);
+void BKE_object_lod_sort(struct Object *ob);
+bool BKE_object_lod_remove(struct Object *ob, int level);
+bool BKE_object_lod_update(struct Object *ob, float camera_position[3]);
+bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene);
+struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene);
+struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
+
 struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, int copy_caches);
 struct Object *BKE_object_copy(struct Object *ob);
 void BKE_object_make_local(struct Object *ob);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index cf9b838..9df523a 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -675,7 +675,7 @@ Material *give_current_material(Object *ob, short act)
 {
 	Material ***matarar, *ma;
 	short *totcolp;
-	
+
 	if (ob == NULL) return NULL;
 	
 	/* if object cannot have material, (totcolp == NULL) */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 0694bde..70b5fb9 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -388,6 +388,8 @@ void BKE_object_free(Object *ob)
 
 	if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids);
 
+	BLI_freelistN(&ob->lodlevels);
+
 	/* Free runtime curves data. */
 	if (ob->curve_cache) {
 		BLI_freelistN(&ob->curve_cache->bev);
@@ -427,6 +429,7 @@ void BKE_object_unlink(Object *ob)
 	ModifierData *md;
 	ARegion *ar;
 	RegionView3D *rv3d;
+	LodLevel *lod;
 	int a, found;
 	
 	unlink_controllers(&ob->controllers);
@@ -608,6 +611,12 @@ void BKE_object_unlink(Object *ob)
 				DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
 		}
 
+		/* levels of detail */
+		for (lod = obt->lodlevels.first; lod; lod = lod->next) {
+			if (lod->source == ob)
+				lod->source = NULL;
+		}
+
 		obt = obt->id.next;
 	}
 	
@@ -1015,6 +1024,138 @@ Object *BKE_object_add(Main *bmain, Scene *scene, int type)
 	return ob;
 }
 
+void BKE_object_lod_add(Object *ob)
+{
+	LodLevel *lod = MEM_callocN(sizeof(LodLevel), "LoD Level");
+	LodLevel *last = ob->lodlevels.last;
+
+	/* If the lod list is empty, initialize it with the base lod level */
+	if (!last) {
+		LodLevel *base = MEM_callocN(sizeof(LodLevel), "Base LoD Level");
+		BLI_addtail(&ob->lodlevels, base);
+		base->flags = OB_LOD_USE_MESH | OB_LOD_USE_MAT;
+		base->source = ob;
+		last = ob->currentlod = base;
+	}
+	
+	lod->distance = last->distance + 25.0f;
+	lod->flags = OB_LOD_USE_MESH | OB_LOD_USE_MAT;
+
+	BLI_addtail(&ob->lodlevels, lod);
+}
+
+static int lod_cmp(void *a, void *b)
+{
+	LodLevel *loda = (LodLevel*)a;
+	LodLevel *lodb =

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list