Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stokes <kupomail@gmail.com>2013-12-18 02:42:47 +0400
committerkupoman <kupomail@gmail.com>2013-12-18 05:03:27 +0400
commite9e08a1d12594eab0e341049fc252ff8578e9333 (patch)
treeac7c15959b03398babb68058f3824c2a4dbff5b7 /source/blender/blenkernel
parent173f7a3d30db8cba95656bf03dc842b9300c2436 (diff)
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
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_object.h8
-rw-r--r--source/blender/blenkernel/intern/material.c2
-rw-r--r--source/blender/blenkernel/intern/object.c154
3 files changed, 163 insertions, 1 deletions
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 434175624b7..e6e6d621ef3 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 cf9b838a7c2..9df523a5bfe 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 0694bde7b91..70b5fb9d420 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 = (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;
@@ -1226,6 +1367,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) &&
@@ -1346,6 +1497,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;