Do not copy the spec during attach.
Use a reference count for managing the memory. PiperOrigin-RevId: 716169486 Change-Id: Id270c4858c17b9250115e9544d5ea143584e2d5f
This commit is contained in:
committed by
Copybara-Service
parent
6436055c6c
commit
c2138c3fb0
+136
-72
@@ -763,6 +763,7 @@ mjCBody::mjCBody(mjCModel* _model) {
|
||||
model = _model;
|
||||
if (_model) compiler = &_model->spec.compiler;
|
||||
|
||||
refcount = 1;
|
||||
mjs_defaultBody(&spec);
|
||||
elemtype = mjOBJ_BODY;
|
||||
parent = nullptr;
|
||||
@@ -872,22 +873,28 @@ mjCBody& mjCBody::operator+=(const mjCFrame& other) {
|
||||
other.model->prefix = other.prefix;
|
||||
other.model->suffix = other.suffix;
|
||||
other.model->StoreKeyframes(model);
|
||||
mjCModel* other_model = other.model;
|
||||
|
||||
// attach defaults
|
||||
if (other.model != model) {
|
||||
mjCDef* subdef = new mjCDef(*other.model->Default());
|
||||
subdef->NameSpace(other.model);
|
||||
if (other_model != model) {
|
||||
mjCDef* subdef = new mjCDef(*other_model->Default());
|
||||
subdef->NameSpace(other_model);
|
||||
*model += *subdef;
|
||||
}
|
||||
|
||||
// copy input frame
|
||||
mjSpec* origin = model->FindSpec(other.compiler);
|
||||
frames.push_back(new mjCFrame(other));
|
||||
mjCFrame* newframe(model->deepcopy_ ? new mjCFrame(other) : (mjCFrame*)&other);
|
||||
frames.push_back(newframe);
|
||||
frames.back()->body = this;
|
||||
frames.back()->model = model;
|
||||
frames.back()->compiler = origin ? &origin->compiler : &model->spec.compiler;
|
||||
frames.back()->frame = other.frame;
|
||||
frames.back()->NameSpace(other.model);
|
||||
if (model->deepcopy_) {
|
||||
frames.back()->NameSpace(other_model);
|
||||
} else {
|
||||
frames.back()->AddRef();
|
||||
}
|
||||
int i = frames.size();
|
||||
last_attached = &frames.back()->spec;
|
||||
|
||||
@@ -909,30 +916,43 @@ mjCBody& mjCBody::operator+=(const mjCFrame& other) {
|
||||
CopyList(cameras, subtree->cameras, fmap, &other);
|
||||
CopyList(lights, subtree->lights, fmap, &other);
|
||||
|
||||
if (!model->deepcopy_) {
|
||||
subtree->SetModel(model);
|
||||
subtree->NameSpace(other_model);
|
||||
}
|
||||
|
||||
int nbodies = (int)subtree->bodies.size();
|
||||
for (int i=0; i<nbodies; i++) {
|
||||
if (!other.IsAncestor(subtree->bodies[i]->frame)) {
|
||||
continue;
|
||||
}
|
||||
bodies.push_back(new mjCBody(*subtree->bodies[i], model)); // triggers recursive call
|
||||
if (model->deepcopy_) {
|
||||
mjCBody* newbody(new mjCBody(*subtree->bodies[i], model)); // triggers recursive call
|
||||
bodies.push_back(newbody);
|
||||
subtree->bodies[i]->ForgetKeyframes();
|
||||
bodies.back()->NameSpace_(other_model, /*propagate=*/ false);
|
||||
} else {
|
||||
bodies.push_back(subtree->bodies[i]);
|
||||
bodies.back()->SetModel(model);
|
||||
bodies.back()->ResetId();
|
||||
bodies.back()->AddRef();
|
||||
}
|
||||
bodies.back()->parent = this;
|
||||
bodies.back()->frame =
|
||||
subtree->bodies[i]->frame ? frames[fmap[subtree->bodies[i]->frame]] : nullptr;
|
||||
bodies.back()->NameSpace_(other.model, /*propagate=*/ false);
|
||||
subtree->bodies[i]->ForgetKeyframes();
|
||||
}
|
||||
|
||||
// attach referencing elements
|
||||
*model += *other.model;
|
||||
*model += *other_model;
|
||||
|
||||
// leave the source model in a clean state
|
||||
if (other.model != model) {
|
||||
other.model->key_pending_.clear();
|
||||
if (other_model != model) {
|
||||
other_model->key_pending_.clear();
|
||||
}
|
||||
|
||||
// clear namespace and return body
|
||||
other.model->prefix.clear();
|
||||
other.model->suffix.clear();
|
||||
other_model->prefix.clear();
|
||||
other_model->suffix.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -948,7 +968,8 @@ void mjCBody::CopyList(std::vector<T*>& dst, const std::vector<T*>& src,
|
||||
continue; // skip if the element is not inside pframe
|
||||
}
|
||||
mjSpec* origin = model->FindSpec(src[i]->compiler);
|
||||
dst.push_back(new T(*src[i]));
|
||||
T* new_obj = model->deepcopy_ ? new T(*src[i]) : src[i];
|
||||
dst.push_back(new_obj);
|
||||
dst.back()->body = this;
|
||||
dst.back()->model = model;
|
||||
dst.back()->compiler = origin ? &origin->compiler : &model->spec.compiler;
|
||||
@@ -956,6 +977,11 @@ void mjCBody::CopyList(std::vector<T*>& dst, const std::vector<T*>& src,
|
||||
dst.back()->CopyPlugin();
|
||||
dst.back()->classname = src[i]->classname;
|
||||
|
||||
// increment refcount if shallow copy is made
|
||||
if (!model->deepcopy_) {
|
||||
dst.back()->AddRef();
|
||||
}
|
||||
|
||||
// assign dst frame to src frame
|
||||
dst.back()->frame = src[i]->frame ? frames[fmap[src[i]->frame]] : nullptr;
|
||||
|
||||
@@ -981,6 +1007,73 @@ mjCBody& mjCBody::operator-=(const mjCBody& subtree) {
|
||||
|
||||
|
||||
|
||||
// set model of this body and its subtree
|
||||
void mjCBody::SetModel(mjCModel* _model) {
|
||||
model = _model;
|
||||
mjSpec* origin = model->FindSpec(mjs_getString(model->spec.modelname));
|
||||
compiler = origin ? &origin->compiler : &model->spec.compiler;
|
||||
|
||||
for (auto& body : bodies) {
|
||||
body->SetModel(_model);
|
||||
}
|
||||
for (auto& frame : frames) {
|
||||
frame->model = _model;
|
||||
frame->compiler = compiler;
|
||||
}
|
||||
for (auto& geom : geoms) {
|
||||
geom->model = _model;
|
||||
geom->compiler = compiler;
|
||||
}
|
||||
for (auto& joint : joints) {
|
||||
joint->model = _model;
|
||||
joint->compiler = compiler;
|
||||
}
|
||||
for (auto& site : sites) {
|
||||
site->model = _model;
|
||||
site->compiler = compiler;
|
||||
}
|
||||
for (auto& camera : cameras) {
|
||||
camera->model = _model;
|
||||
camera->compiler = compiler;
|
||||
}
|
||||
for (auto& light : lights) {
|
||||
light->model = _model;
|
||||
light->compiler = compiler;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// reset ids of all objects in this body
|
||||
void mjCBody::ResetId() {
|
||||
id = -1;
|
||||
for (auto& body : bodies) {
|
||||
body->ResetId();
|
||||
}
|
||||
for (auto& frame : frames) {
|
||||
frame->id = -1;
|
||||
}
|
||||
for (auto& geom : geoms) {
|
||||
geom->id = -1;
|
||||
}
|
||||
for (auto& joint : joints) {
|
||||
joint->id = -1;
|
||||
joint->qposadr_ = -1;
|
||||
joint->dofadr_ = -1;
|
||||
}
|
||||
for (auto& site : sites) {
|
||||
site->id = -1;
|
||||
}
|
||||
for (auto& camera : cameras) {
|
||||
camera->id = -1;
|
||||
}
|
||||
for (auto& light : lights) {
|
||||
light->id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCBody::PointToLocal() {
|
||||
spec.element = static_cast<mjsElement*>(this);
|
||||
spec.name = &name;
|
||||
@@ -1012,26 +1105,13 @@ void mjCBody::CopyPlugin() {
|
||||
|
||||
// destructor
|
||||
mjCBody::~mjCBody() {
|
||||
// delete objects allocated here
|
||||
for (int i=0; i<bodies.size(); i++) delete bodies[i];
|
||||
for (int i=0; i<geoms.size(); i++) delete geoms[i];
|
||||
for (int i=0; i<frames.size(); i++) delete frames[i];
|
||||
for (int i=0; i<joints.size(); i++) delete joints[i];
|
||||
for (int i=0; i<sites.size(); i++) delete sites[i];
|
||||
for (int i=0; i<cameras.size(); i++) delete cameras[i];
|
||||
for (int i=0; i<lights.size(); i++) delete lights[i];
|
||||
|
||||
bodies.clear();
|
||||
geoms.clear();
|
||||
frames.clear();
|
||||
joints.clear();
|
||||
sites.clear();
|
||||
cameras.clear();
|
||||
lights.clear();
|
||||
|
||||
if (spec.plugin.active && spec.plugin.name->empty() && model) {
|
||||
model->DeleteElement(spec.plugin.element);
|
||||
}
|
||||
for (int i=0; i<bodies.size(); i++) bodies[i]->Release();
|
||||
for (int i=0; i<geoms.size(); i++) geoms[i]->Release();
|
||||
for (int i=0; i<frames.size(); i++) frames[i]->Release();
|
||||
for (int i=0; i<joints.size(); i++) joints[i]->Release();
|
||||
for (int i=0; i<sites.size(); i++) sites[i]->Release();
|
||||
for (int i=0; i<cameras.size(); i++) cameras[i]->Release();
|
||||
for (int i=0; i<lights.size(); i++) lights[i]->Release();
|
||||
}
|
||||
|
||||
|
||||
@@ -1840,19 +1920,27 @@ mjCFrame& mjCFrame::operator+=(const mjCBody& other) {
|
||||
other.model->StoreKeyframes(model);
|
||||
other.model->prefix = "";
|
||||
other.model->suffix = "";
|
||||
mjCModel* other_model = other.model;
|
||||
|
||||
mjCBody* subtree = new mjCBody(other, model);
|
||||
other.ForgetKeyframes();
|
||||
other.model->prefix = subtree->prefix;
|
||||
other.model->suffix = subtree->suffix;
|
||||
// attach or copy the subtree
|
||||
mjCBody* subtree = model->deepcopy_ ? new mjCBody(other, model) : (mjCBody*)&other;
|
||||
if (model->deepcopy_) {
|
||||
other.ForgetKeyframes();
|
||||
} else {
|
||||
subtree->SetModel(model);
|
||||
subtree->ResetId();
|
||||
subtree->AddRef();
|
||||
}
|
||||
other_model->prefix = subtree->prefix;
|
||||
other_model->suffix = subtree->suffix;
|
||||
subtree->SetParent(body);
|
||||
subtree->SetFrame(this);
|
||||
subtree->NameSpace(other.model);
|
||||
subtree->NameSpace(other_model);
|
||||
|
||||
// attach defaults
|
||||
if (other.model != model) {
|
||||
mjCDef* subdef = new mjCDef(*other.model->Default());
|
||||
subdef->NameSpace(other.model);
|
||||
if (other_model != model) {
|
||||
mjCDef* subdef = new mjCDef(*other_model->Default());
|
||||
subdef->NameSpace(other_model);
|
||||
*model += *subdef;
|
||||
}
|
||||
|
||||
@@ -1861,16 +1949,16 @@ mjCFrame& mjCFrame::operator+=(const mjCBody& other) {
|
||||
last_attached = &body->bodies.back()->spec;
|
||||
|
||||
// attach referencing elements
|
||||
*model += *other.model;
|
||||
*model += *other_model;
|
||||
|
||||
// leave the source model in a clean state
|
||||
if (other.model != model) {
|
||||
other.model->key_pending_.clear();
|
||||
if (other_model != model) {
|
||||
other_model->key_pending_.clear();
|
||||
}
|
||||
|
||||
// clear suffixes and return
|
||||
other.model->suffix.clear();
|
||||
other.model->prefix.clear();
|
||||
other_model->suffix.clear();
|
||||
other_model->prefix.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -2221,14 +2309,6 @@ mjCGeom::mjCGeom(const mjCGeom& other) {
|
||||
|
||||
|
||||
|
||||
mjCGeom::~mjCGeom() {
|
||||
if (spec.plugin.active && spec.plugin.name->empty() && model) {
|
||||
model->DeleteElement(spec.plugin.element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
mjCGeom& mjCGeom::operator=(const mjCGeom& other) {
|
||||
if (this != &other) {
|
||||
this->spec = other.spec;
|
||||
@@ -4591,7 +4671,7 @@ void mjCMaterial::CopyFromSpec() {
|
||||
void mjCMaterial::NameSpace(const mjCModel* m) {
|
||||
mjCBase::NameSpace(m);
|
||||
for (int i=0; i<mjNTEXROLE; i++) {
|
||||
if (!spec_textures_[i].empty() && model != m) {
|
||||
if (!spec_textures_[i].empty()) {
|
||||
spec_textures_[i] = m->prefix + spec_textures_[i] + m->suffix;
|
||||
}
|
||||
}
|
||||
@@ -5657,14 +5737,6 @@ mjCActuator::mjCActuator(const mjCActuator& other) {
|
||||
|
||||
|
||||
|
||||
mjCActuator::~mjCActuator() {
|
||||
if (spec.plugin.active && spec.plugin.name->empty() && model) {
|
||||
model->DeleteElement(spec.plugin.element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
mjCActuator& mjCActuator::operator=(const mjCActuator& other) {
|
||||
if (this != &other) {
|
||||
this->spec = other.spec;
|
||||
@@ -6033,14 +6105,6 @@ mjCSensor::mjCSensor(const mjCSensor& other) {
|
||||
|
||||
|
||||
|
||||
mjCSensor::~mjCSensor() {
|
||||
if (spec.plugin.active && spec.plugin.name->empty() && model) {
|
||||
model->DeleteElement(spec.plugin.element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
mjCSensor& mjCSensor::operator=(const mjCSensor& other) {
|
||||
if (this != &other) {
|
||||
this->spec = other.spec;
|
||||
|
||||
Reference in New Issue
Block a user