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:
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;