diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_object.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/material.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 154 |
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; |