1
1

Compare commits

...

54 Commits

Author SHA1 Message Date
0aa392d2ff Merged revisions 60248-60717 from trunk/blender 2013-10-13 20:59:55 +00:00
6167313105 Making the level of detail UI only available while the renderer is set to "Blender Game" since it does not help the viewport other than as a preview for the game engine. 2013-09-22 00:52:08 +00:00
ee26dba873 Fixing a crash that occurred when duplicating an object with no levels of detail. 2013-09-21 07:18:42 +00:00
ad94e0b860 Merged revision(s) 59972-60247 from trunk/blender 2013-09-21 06:39:10 +00:00
9fc387dee3 Fixing up file loading so that objects with levels of details properly have their levels of details brought with them when linked or appended. 2013-09-20 00:41:26 +00:00
1a100a3124 Moving some code out of rna_object.c to object.c for updating the level of detail distance. 2013-09-14 01:40:07 +00:00
b247e869ae Using NC_OBJECT|ND_LOD for notifications instead of NC_LOD. 2013-09-14 01:29:38 +00:00
aeaf0cf32f Simplifying the usage of BKE_object_lod_meshob_get and BKE_object_lod_matob_get, and cleaning up the code lod code in object.c.
The level of detail data now uses a bitfield for flags such as use_mesh and use_mat. The few files out there currently using levels of detail will need to renable those options.
2013-09-14 00:32:58 +00:00
3757456a08 Expanding abbreviations used in some level of detail operator names. 2013-09-14 00:01:05 +00:00
6338da9dcd Removing the need to have a LodLevel for every object by adding a few checks for special cases. 2013-09-14 00:00:17 +00:00
77d8e4992e Changing the label for "Setup Level of Details By Name" to "Setup Levels of Detail By Name" 2013-09-13 23:58:47 +00:00
43ab2e5184 Rewriting copy_object_lod to use BLI_duplicatelist. 2013-09-13 23:13:49 +00:00
eebd916aca Renaming BKE_object_lod_check to BKE_object_lod_is_usable to make what is being checked more clear. 2013-09-13 23:07:13 +00:00
3b5d72f1fc Moving the definition for KX_GameObject::AddLodMesh from the header file to the source file. 2013-09-10 02:17:21 +00:00
aa07acdca6 Merged revisions 58706-59971 from trunk/blender 2013-09-10 00:27:21 +00:00
a01c6c61c2 Moved the level of detail update after culling, and only doing the update for objects that have not been culled. 2013-07-31 05:42:32 +00:00
c984e7c992 Code cleanup. Removing dead code, adding comments, improving code readability, etc. 2013-07-31 05:33:28 +00:00
7e3de1c868 Merged revisions 58516-58705 from trunk/blender 2013-07-29 04:52:41 +00:00
ba856c1719 Merged revisions 57983-58515 from trunk/blender 2013-07-23 00:56:38 +00:00
600ed7cd72 Increasing the default distance between levels of detail from 10 to 25. 2013-07-12 20:49:22 +00:00
924b6b16d9 Limiting the target setting on the level of detail generation operator to a range of 0.0 - 1.0. 2013-07-12 20:47:24 +00:00
626523cc1d Fixing an error caused by changing the settings of the level of detail generation operator. 2013-07-11 20:48:11 +00:00
74f3fb4a64 Adding an operator to generate levels of detail from the selected object using the decimate modifier. This operator has options to control the number of levels, the amount of reduction, and whether or not to "package" the levels. Packaging means the levels of details are generated in such a way that they can easily be used as dupligroups. 2013-07-11 01:05:14 +00:00
99904ff39b Fixing a problem where libloaded objects had a NULL source for their first level of detail. 2013-07-09 00:48:46 +00:00
eea8747b66 Reworking the level of detail UI so that the add button is on the bottom and a menu has been added for level of detail tools. So far these tools include a set by name operator that finds appropriately named models in the scene to use for detail levels, and a clear all operator for removing all levels of detail from an object. 2013-07-07 05:19:28 +00:00
3b2c1d50ed Fixing a game engine crash when level of detail sources are non mesh objects (e.g. lamps, cameras, etc). 2013-07-06 06:51:37 +00:00
3ce8456887 Merged revisions 57870-57983 from trunk/blender 2013-07-04 22:41:57 +00:00
9cf39928ef Cleaning up the game engine level of detail logic to avoid crashes with levels that have no source object defined. 2013-07-04 02:39:58 +00:00
d810299b49 The level of detail system now works in the game engine with group instances. This required the game engine to reimplement some of the level of detail logic, but not too much. 2013-07-03 03:18:44 +00:00
872dc31765 Starting support for mesh and material levels of detail in the game engine. They work for simple cases, but break in more advanced usage such as dupligroups. 2013-07-01 09:12:40 +00:00
26bacdebed Changed BKE_object_lod_update to return a bool indicating if the lod level has changed. 2013-07-01 09:10:05 +00:00
495d00f0ae Moving the material level of detail switch to avoid problems with the material panel. 2013-06-30 08:29:42 +00:00
1c47d1fa02 Merged revisions 57538-57869 from trunk/blender 2013-06-29 07:00:38 +00:00
3ac2b4e1a6 Group instances now update their base objects' level of detail temporarily from their own position. This allows group instances to behave properly with levels of detail. 2013-06-28 00:01:37 +00:00
10a57d7f84 Removing an unnecessary vector copy when updating levels of detail. 2013-06-27 23:43:54 +00:00
6fca4ab09e Duplicate objects no longer share level of detail settings. 2013-06-27 22:01:25 +00:00
0f67698ace The 3Dview now redraws on changes to level of detail settings. Also, changing the distance values on levels of details now causes the levels of detail to be sorted. 2013-06-27 00:04:47 +00:00
593093f0dd Fixing a crash that occurred when give_current_material was passed a NULL object. 2013-06-26 23:37:31 +00:00
e08e2bd90f Fixed a crash that occurred when an object being used as a level of detail was deleted. 2013-06-26 23:35:45 +00:00
1362c9f6ce Fixing a minor memory leak caused by not freeing the level of detail list when an object is freed. 2013-06-26 23:30:11 +00:00
7e95068429 Removing a level of detail now causes the view to update. Also making sure to free the removed level of detail now. 2013-06-26 20:48:49 +00:00
ab859a3357 Fixing some crashes with the level of detail system with the default blendfile. 2013-06-26 10:05:53 +00:00
8243320622 Fixing a crash that occurred when switching to a level of detail with no object specified. 2013-06-26 09:36:59 +00:00
0f0438f406 Material level of detail is now working. Material levels of detail appear in all editing modes (sculpt, edit, etc). 2013-06-26 06:16:39 +00:00
a27959bb09 When getting the mesh source object, levels that are not enabled for mesh LoD as well as non-mesh objects are now ignored, and the next appropriate LoD object is found. 2013-06-26 05:45:36 +00:00
3a7e61fe10 Correcting a logic error that caused some levels of details to be skipped when increasing detail. 2013-06-26 05:18:08 +00:00
91d24ee4a4 Basic mesh level of detail is now working in the viewport. It should only display levels of detail if you are in object mode, or the object is not the currently active object. 2013-06-26 01:07:31 +00:00
e7861151a2 Levels of detail are now properly saved and loaded. 2013-06-25 21:06:35 +00:00
c4d2a9301c Adding a do_version for the base LoD level on objects. 2013-06-24 23:38:57 +00:00
b6cb40040c Adding code to detect when an LoD switch is needed in the viewport. It currently just prints to the console. This print will be replaced with actual switching code in the near future. 2013-06-24 23:13:40 +00:00
863a2cb35e The start of the new level of detail system. The UI properly modifies level of detail information on the object, and allows for adding and removing levels of detail. No level of detail selection or switching occurs yet. 2013-06-21 07:04:54 +00:00
7546fd071d Branching from Trunk/blender to soc-2013-bge 2013-06-18 05:16:15 +00:00
eddbe08ca1 Deleting soc-2013-bge to rebranch from current Trunk 2013-06-18 05:14:30 +00:00
301d2c44ce gsoc 2013 branch soc-2013-bge 2013-06-12 04:02:53 +00:00
26 changed files with 692 additions and 6 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 251 KiB

View File

@@ -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'}

View File

@@ -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"

View File

@@ -84,6 +84,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);

View File

@@ -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) */

View File

@@ -356,6 +356,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);
@@ -395,6 +397,7 @@ void BKE_object_unlink(Object *ob)
ModifierData *md;
ARegion *ar;
RegionView3D *rv3d;
LodLevel *lod;
int a, found;
unlink_controllers(&ob->controllers);
@@ -573,6 +576,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;
}
@@ -876,6 +885,7 @@ static const char *get_obdata_defname(int type)
Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
{
Object *ob;
LodLevel *base;
if (!name)
name = get_obdata_defname(type);
@@ -980,6 +990,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 = (LodLevel*)b;
if (loda->distance < lodb->distance) return -1;
return loda->distance > lodb->distance;
}
void BKE_object_lod_sort(Object *ob)
{
BLI_sortlist(&ob->lodlevels, lod_cmp);
}
bool BKE_object_lod_remove(Object *ob, int level)
{
LodLevel *rem;
if (level < 1 || level > BLI_countlist(&ob->lodlevels) - 1)
return false;
rem = BLI_findlink(&ob->lodlevels, level);
if (rem == ob->currentlod) {
ob->currentlod = rem->prev;
}
BLI_remlink(&ob->lodlevels, rem);
MEM_freeN(rem);
/* If there are no user defined lods, remove the base lod as well */
if (BLI_countlist(&ob->lodlevels) == 1) {
LodLevel *base = ob->lodlevels.first;
BLI_remlink(&ob->lodlevels, base);
MEM_freeN(base);
ob->currentlod = NULL;
}
return true;
}
static LodLevel* lod_level_select(Object *ob, float cam_loc[3])
{
LodLevel *current = ob->currentlod;
float ob_loc[3], delta[3];
float distance2;
if (!current) return NULL;
copy_v3_v3(ob_loc, ob->obmat[3]);
sub_v3_v3v3(delta, ob_loc, cam_loc);
distance2 = len_squared_v3(delta);
/* check for higher LoD */
if (distance2 < current->distance*current->distance) {
while (current->prev && distance2 < current->distance*current->distance) {
current = current->prev;
}
}
/* check for lower LoD */
else {
while (current->next && distance2 > current->next->distance*current->next->distance) {
current = current->next;
}
}
return current;
}
bool BKE_object_lod_is_usable(Object *ob, Scene *scene)
{
bool active = (scene) ? ob == OBACT : 0;
return (ob->mode == OB_MODE_OBJECT || !active);
}
bool BKE_object_lod_update(Object *ob, float camera_position[3])
{
LodLevel* cur_level = ob->currentlod;
LodLevel* new_level = lod_level_select(ob, camera_position);
if (new_level != cur_level) {
ob->currentlod = new_level;
return true;
}
return false;
}
static Object *lod_ob_get(Object *ob, Scene *scene, int flag)
{
LodLevel *current = ob->currentlod;
if (!current || !BKE_object_lod_is_usable(ob, scene))
return ob;
while( current->prev && (!(current->flags & flag) || !current->source || current->source->type != OB_MESH)) {
current = current->prev;
}
return current->source;
}
struct Object *BKE_object_lod_meshob_get(Object *ob, Scene *scene)
{
return lod_ob_get(ob, scene, OB_LOD_USE_MESH);
}
struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene)
{
return lod_ob_get(ob, scene, OB_LOD_USE_MAT);
}
SoftBody *copy_softbody(SoftBody *sb, int copy_caches)
{
SoftBody *sbn;
@@ -1191,6 +1333,16 @@ static void copy_object_pose(Object *obn, Object *ob)
}
}
static void copy_object_lod(Object *obn, Object *ob)
{
BLI_duplicatelist(&obn->lodlevels, &ob->lodlevels);
if (obn->lodlevels.first)
((LodLevel*)obn->lodlevels.first)->source = obn;
obn->currentlod = (LodLevel*) obn->lodlevels.first;
}
bool BKE_object_pose_context_check(Object *ob)
{
if ((ob) &&
@@ -1306,6 +1458,9 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
obn->mpath = NULL;
copy_object_lod(obn, ob);
/* Copy runtime surve data. */
obn->curve_cache = NULL;

View File

@@ -4520,6 +4520,16 @@ static void lib_link_object(FileData *fd, Main *main)
ob->rigidbody_constraint->ob1 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob1);
ob->rigidbody_constraint->ob2 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob2);
}
{
LodLevel *level;
for (level = ob->lodlevels.first; level; level = level->next) {
level->source = newlibadr(fd, ob->id.lib, level->source);
if (!level->source && level == ob->lodlevels.first)
level->source = ob;
}
}
}
}
@@ -5045,6 +5055,9 @@ static void direct_link_object(FileData *fd, Object *ob)
if (ob->sculpt) {
ob->sculpt = MEM_callocN(sizeof(SculptSession), "reload sculpt session");
}
link_list(fd, &ob->lodlevels);
ob->currentlod = ob->lodlevels.first;
}
/* ************ READ SCENE ***************** */
@@ -10705,6 +10718,12 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
expand_doit(fd, mainvar, ob->rigidbody_constraint->ob2);
}
if (ob->currentlod) {
LodLevel *level;
for (level = ob->lodlevels.first; level; level = level->next) {
expand_doit(fd, mainvar, level->source);
}
}
}
static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)

View File

@@ -1532,6 +1532,8 @@ static void write_objects(WriteData *wd, ListBase *idbase)
write_particlesystems(wd, &ob->particlesystem);
write_modifiers(wd, &ob->modifiers);
writelist(wd, DATA, "LodLevel", &ob->lodlevels);
}
ob= ob->id.next;
}

View File

@@ -47,6 +47,7 @@ set(SRC
object_group.c
object_hook.c
object_lattice.c
object_lod.c
object_modifier.c
object_ops.c
object_relations.c

View File

@@ -249,5 +249,9 @@ void OBJECT_OT_group_remove(struct wmOperatorType *ot);
/* object_bake.c */
void OBJECT_OT_bake_image(wmOperatorType *ot);
/* object_lod.c */
void OBJECT_OT_lod_add(struct wmOperatorType *ot);
void OBJECT_OT_lod_remove(struct wmOperatorType *ot);
#endif /* __OBJECT_INTERN_H__ */

View File

@@ -0,0 +1,102 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) Blender Foundation
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/object/object_lod.c
* \ingroup edobj
*/
#include "DNA_object_types.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "ED_screen.h"
#include "ED_object.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "object_intern.h"
static int object_lod_add_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
BKE_object_lod_add(ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_lod_add(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Add Level of Detail";
ot->description = "Add a level of detail to this object";
ot->idname = "OBJECT_OT_lod_add";
/* api callbacks */
ot->exec = object_lod_add_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_lod_remove_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
int index = RNA_int_get(op->ptr, "index");
if(!BKE_object_lod_remove(ob, index))
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_OBJECT|ND_LOD, CTX_wm_view3d(C));
return OPERATOR_FINISHED;
}
void OBJECT_OT_lod_remove(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove Level of Detail";
ot->description = "Remove a level of detail from this object";
ot->idname = "OBJECT_OT_lod_remove";
/* api callbacks */
ot->exec = object_lod_remove_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
ot->prop = RNA_def_int(ot->srna, "index", 1, 1, INT_MAX, "Index", "", 1, INT_MAX);
}

View File

@@ -238,6 +238,9 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_bake_image);
WM_operatortype_append(OBJECT_OT_drop_named_material);
WM_operatortype_append(OBJECT_OT_lod_add);
WM_operatortype_append(OBJECT_OT_lod_remove);
}
void ED_operatormacros_object(void)

View File

@@ -3358,7 +3358,7 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
Object *ob = base->object;
Object *ob = BKE_object_lod_meshob_get(base->object, scene);
Mesh *me = ob->data;
Material *ma = give_current_material(ob, 1);
const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene));

View File

@@ -788,6 +788,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
case ND_CONSTRAINT:
case ND_KEYS:
case ND_PARTICLE:
case ND_LOD:
ED_region_tag_redraw(ar);
break;
}

View File

@@ -2003,6 +2003,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
{
RegionView3D *rv3d = ar->regiondata;
ListBase *lb;
LodLevel *savedlod;
DupliObject *dob_prev = NULL, *dob, *dob_next = NULL;
Base tbase = {NULL};
BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
@@ -2023,6 +2024,13 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
tbase.object = dob->ob;
/* Make sure lod is updated from dupli's position */
copy_m4_m4(dob->ob->obmat, dob->mat);
savedlod = dob->ob->currentlod;
BKE_object_lod_update(dob->ob, rv3d->viewinv[3]);
/* extra service: draw the duplicator in drawtype of parent, minimum taken
* to allow e.g. boundbox box objects in groups for LOD */
dt = tbase.object->dt;
@@ -2093,13 +2101,13 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
glLoadMatrixf(rv3d->viewmat);
}
else {
copy_m4_m4(dob->ob->obmat, dob->mat);
draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
}
tbase.object->dt = dt;
tbase.object->dtx = dtx;
tbase.object->transflag = transflag;
tbase.object->currentlod = savedlod;
}
/* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
@@ -3225,6 +3233,18 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
}
}
static void update_lods(Scene *scene, float camera_pos[3])
{
Scene *sce_iter;
Base *base;
Object *ob;
for (SETLOOPER(scene, sce_iter, base)) {
ob = base->object;
BKE_object_lod_update(ob, camera_pos);
}
}
/* warning: this function has duplicate drawing in ED_view3d_draw_offscreen() */
static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit)
{
@@ -3247,6 +3267,9 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
/* setup view matrices */
view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
/* Make sure LoDs are up to date */
update_lods(scene, rv3d->viewinv[3]);
/* clear the background */
view3d_main_area_clear(scene, v3d, ar);

View File

@@ -1388,6 +1388,8 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
int gamma = BKE_scene_check_color_management_enabled(scene);
int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
int use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP); /* assumes v3d->defmaterial->preview is set */
ob = BKE_object_lod_matob_get(ob, scene);
/* initialize state */
memset(&GMS, 0, sizeof(GMS));

View File

@@ -105,6 +105,13 @@ enum {
BOUNDBOX_DIRTY = (1 << 1),
};
typedef struct LodLevel {
struct LodLevel *next, *prev;
struct Object *source;
int flags;
float distance;
} LodLevel;
typedef struct Object {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -279,6 +286,9 @@ typedef struct Object {
float ima_ofs[2]; /* offset for image empties */
ListBase lodlevels; /* contains data for levels of detail */
LodLevel *currentlod;
/* Runtime valuated curve-specific data, not stored in the file */
struct CurveCache *curve_cache;
} Object;
@@ -470,6 +480,12 @@ enum {
OB_BOUND_CAPSULE = 7,
};
/* lod flags */
enum {
OB_LOD_USE_MESH = 1 << 0,
OB_LOD_USE_MAT = 1 << 1,
};
/* **************** BASE ********************* */

View File

@@ -40,6 +40,7 @@
#include "DNA_meta_types.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BKE_paint.h"
#include "BKE_editmesh.h"
@@ -1458,6 +1459,11 @@ int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
return (ss && ss->bm);
}
static void rna_Object_lod_distance_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
BKE_object_lod_sort(ob);
}
#else
static void rna_def_vertex_group(BlenderRNA *brna)
@@ -2013,6 +2019,41 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
}
static void rna_def_object_lodlevel(BlenderRNA* brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "LodLevel", NULL);
RNA_def_struct_sdna(srna, "LodLevel");
prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "distance");
RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_text(prop, "Distance", "Distance to begin using this level of detail");
RNA_def_property_update(prop, NC_OBJECT|ND_LOD, "rna_Object_lod_distance_update");
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "source");
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Object", "Object to use for this level of detail");
RNA_def_property_update(prop, NC_OBJECT|ND_LOD, NULL);
prop = RNA_def_property(srna, "use_mesh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", OB_LOD_USE_MESH);
RNA_def_property_ui_text(prop, "Use Mesh", "Use the mesh from this object at this level of detail");
RNA_def_property_ui_icon(prop, ICON_MESH_DATA, 0);
RNA_def_property_update(prop, NC_OBJECT|ND_LOD, NULL);
prop = RNA_def_property(srna, "use_material", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", OB_LOD_USE_MAT);
RNA_def_property_ui_text(prop, "Use Material", "Use the material from this object at this level of detail");
RNA_def_property_ui_icon(prop, ICON_MATERIAL, 0);
RNA_def_property_update(prop, NC_OBJECT|ND_LOD, NULL);
}
static void rna_def_object(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2673,6 +2714,13 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Dynamic Topology Sculpting", NULL);
/* Levels of Detail */
prop = RNA_def_property(srna, "lod_levels", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "lodlevels", NULL);
RNA_def_property_struct_type(prop, "LodLevel");
RNA_def_property_ui_text(prop, "Level of Detail Levels", "A collection of detail levels to automatically switch between");
RNA_def_property_update(prop, NC_OBJECT|ND_LOD, NULL);
RNA_api_object(srna);
}
@@ -2783,6 +2831,7 @@ void RNA_def_object(BlenderRNA *brna)
rna_def_material_slot(brna);
rna_def_dupli_object(brna);
RNA_define_animate_sdna(true);
rna_def_object_lodlevel(brna);
}
#endif

View File

@@ -297,6 +297,7 @@ typedef struct wmNotifier {
#define ND_PARTICLE (27<<16)
#define ND_POINTCACHE (28<<16)
#define ND_PARENT (29<<16)
#define ND_LOD (30<<16)
/* NC_MATERIAL Material */
#define ND_SHADING (30<<16)

View File

@@ -96,6 +96,7 @@
#include "KX_SoftBodyDeformer.h"
//#include "BL_ArmatureController.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BlenderWorldInfo.h"
#include "KX_KetsjiEngine.h"
@@ -1076,8 +1077,15 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
RAS_MeshObject *meshobj;
int lightlayer = blenderobj ? blenderobj->lay:(1<<20)-1; // all layers if no object.
if ((meshobj = converter->FindGameMesh(mesh/*, ob->lay*/)) != NULL)
return meshobj;
// Without checking names, we get some reuse we don't want that can cause
// problems with material LoDs.
if ((meshobj = converter->FindGameMesh(mesh/*, ob->lay*/)) != NULL) {
STR_String bge_name = meshobj->GetName();
STR_String blender_name = ((Mesh*)blenderobj->data)->id.name+2;
if (bge_name == blender_name)
return meshobj;
}
// Get DerivedMesh data
DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj);
DM_ensure_tessface(dm);
@@ -1989,6 +1997,24 @@ static KX_GameObject *gameobject_from_blenderobject(
// set transformation
gameobj->AddMesh(meshobj);
// gather levels of detail
if (BLI_countlist(&ob->lodlevels) > 1) {
LodLevel *lod = ((LodLevel*)ob->lodlevels.first)->next;
Mesh* lodmesh = mesh;
Object* lodmatob = ob;
gameobj->AddLodMesh(meshobj);
for (; lod; lod = lod->next) {
if (!lod->source || lod->source->type != OB_MESH) continue;
if (lod->flags & OB_LOD_USE_MESH) {
lodmesh = static_cast<Mesh*>(lod->source->data);
}
if (lod->flags & OB_LOD_USE_MAT) {
lodmatob = lod->source;
}
gameobj->AddLodMesh(BL_ConvertMesh(lodmesh, lodmatob, kxscene, converter, libloading));
}
}
// for all objects: check whether they want to
// respond to updates

View File

@@ -2047,6 +2047,10 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
cam->NodeUpdateGS(0.f);
scene->CalculateVisibleMeshes(m_rasterizer,cam);
// update levels of detail
scene->UpdateObjectLods();
scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
}

View File

@@ -72,6 +72,8 @@ typedef unsigned long uint_ptr;
#include "NG_NetworkScene.h" //Needed for sendMessage()
#include "KX_ObstacleSimulation.h"
#include "BKE_object.h"
#include "BL_ActionManager.h"
#include "BL_Action.h"
@@ -727,6 +729,43 @@ void KX_GameObject::RemoveMeshes()
m_meshes.clear();
}
void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh)
{
m_lodmeshes.push_back(mesh);
}
void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos)
{
// Handle dupligroups
if (this->m_pInstanceObjects) {
KX_GameObject * instob;
int count = this->m_pInstanceObjects->GetCount();
for (int i = 0; i < count; i++) {
instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i);
instob->UpdateLod(cam_pos);
}
}
if (this->m_lodmeshes.empty()) return;
MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos;
float distance2 = delta.length2();
int level = 0;
Object *bob = this->GetBlenderObject();
LodLevel *lod = (LodLevel*) bob->lodlevels.first;
for (; lod; lod = lod->next, level++) {
if (!lod->source) level--;
if (!lod->next || lod->next->distance * lod->next->distance > distance2) break;
}
RAS_MeshObject *mesh = this->m_lodmeshes[level];
if (mesh != this->m_meshes[0]) {
this->GetScene()->ReplaceMesh(this, mesh, true, false);
}
}
void KX_GameObject::UpdateTransform()
{
// HACK: saves function call for dynamic object, they are handled differently

View File

@@ -88,6 +88,7 @@ protected:
STR_String m_text;
int m_layer;
std::vector<RAS_MeshObject*> m_meshes;
std::vector<RAS_MeshObject*> m_lodmeshes;
SG_QList m_meshSlots; // head of mesh slots of this
struct Object* m_pBlenderObject;
struct Object* m_pBlenderGroupObject;
@@ -757,6 +758,23 @@ public:
m_meshes.push_back(mesh);
}
/**
* Add a level of detail mesh to the object. These should
* be added in order.
*/
void
AddLodMesh(
RAS_MeshObject* mesh
);
/**
* Updates the current lod level based on distance from camera.
*/
void
UpdateLod(
MT_Vector3 &cam_pos
);
/**
* Pick out a mesh associated with the integer 'num'.
*/

View File

@@ -1330,6 +1330,9 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
scene->CalculateVisibleMeshes(m_rasterizer,cam);
// update levels of detail
scene->UpdateObjectLods();
m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_RENDER);

View File

@@ -1694,6 +1694,19 @@ void KX_Scene::RenderFonts()
}
}
void KX_Scene::UpdateObjectLods(void)
{
KX_GameObject* gameobj;
MT_Vector3 cam_pos = this->m_active_camera->NodeGetWorldPosition();
for (int i = 0; i < this->GetObjectList()->GetCount(); i++) {
gameobj = (KX_GameObject*) GetObjectList()->GetValue(i);
if (!gameobj->GetCulled()){
gameobj->UpdateLod(cam_pos);
}
}
}
void KX_Scene::UpdateObjectActivity(void)
{
if (m_activity_culling) {

View File

@@ -545,6 +545,9 @@ public:
// Resume a suspended scene.
void Resume();
// Update the mesh for objects based on level of detail settings
void UpdateObjectLods(void);
// Update the activity box settings for objects in this scene, if needed.
void UpdateObjectActivity(void);