multimaterial support, "preset"

each preset contains visibility, flags and material
This commit is contained in:
2023-05-16 18:18:26 +03:00
parent c275d006d5
commit 484a7f972f
11 changed files with 523 additions and 259 deletions

View File

@@ -91,6 +91,7 @@ void Scene::assignFrom(const Scene * s) {
addObject(s->root_->child(i)->clone());
// qDebug() << i << o->child(i)->pos();
}
setPreset(s->preset());
tree_changed = mat_changed = lights_changed = need_reload_materials = tree_struct_changed = true;
}
@@ -321,11 +322,16 @@ Material * Scene::newMaterial(const QString & name) {
void Scene::removeMaterial(Material * m) {
if (!m || !materials.contains(m)) return;
ObjectBaseList ol = root_->children(true);
foreach(ObjectBase * o, ol)
if (o->material_ == m) o->setMaterial(0);
for (auto * o: ol)
for (auto & p: o->presets)
if (p.material == m) {
p.material = nullptr;
o->setObjectsChanged();
}
materials.removeAll(m);
changed_materials.removeAll(m);
mat_changed = true;
mat_changed = true;
tree_changed = true;
}
@@ -349,6 +355,15 @@ void Scene::removeLight(Light * l) {
}
void Scene::setPreset(int preset) {
if (cur_preset == preset) return;
cur_preset = preset;
root_->setPreset(cur_preset);
mat_changed = tree_changed = tree_struct_changed = lights_changed = true;
emit presetChanged(cur_preset);
}
void Scene::dump() {
qDebug() << "Scene" << name();
qDebug() << "Meshes:" << geometries.size();
@@ -371,28 +386,31 @@ void Scene::attachObject(ObjectBase * o) {
o->setMesh(attachMesh(o->mesh()));
setObjectMeshChanged(o);
}
if (o->material()) { // search suitable material in this scene
uint ohash = o->material()->hash();
bool need_new = true;
foreach(Material * m, materials) {
if (m == o->material()) { // already exists by ptr
need_new = false;
break;
for (auto & p: o->presets) {
if (p.material) { // search suitable material in this scene
uint ohash = p.material->hash();
bool need_new = true;
foreach(Material * m, materials) {
if (m == p.material) { // already exists by ptr
need_new = false;
break;
}
if (m->hash() == ohash) { // already exists by hash
need_new = false;
p.material = m;
break;
}
}
if (m->hash() == ohash) { // already exists by hash
need_new = false;
o->setMaterial(m);
break;
if (need_new) { // need to clone material and add to scene
Material * nmat = new Material();
*nmat = *(p.material);
nmat->setMapsChanged();
p.material = nmat;
materials << nmat;
}
}
if (need_new) { // need to clone material and add to scene
Material * nmat = new Material();
*nmat = *(o->material());
nmat->setMapsChanged();
o->setMaterial(nmat);
materials << nmat;
}
}
o->setPreset(cur_preset);
setTreeStructChanged();
}
@@ -507,15 +525,25 @@ void Scene::destroyUnused(QOpenGLExtraFunctions * f) {
QDataStream & operator<<(QDataStream & s, const Scene * p) {
ChunkStream cs;
// qDebug() << "place" << p->name() << "...";
QVector<short> geom_ind, mat_ind;
QVector<short> geom_ind, mats;
QVector<QVector<short>> mat_ind;
ObjectBaseList cl = p->root_->children(true);
geom_ind.reserve(cl.size());
mat_ind.reserve(cl.size());
foreach(ObjectBase * c, cl) {
for (auto * c: cl) {
geom_ind << p->geometries.indexOf(c->mesh());
mat_ind << p->materials.indexOf(c->material());
mats.clear();
for (auto i: c->presets)
mats << p->materials.indexOf(i.material);
mat_ind << mats;
}
cs.add(1, p->name_).add(10, p->geometries).add(11, p->materials).add(20, p->root_).add(21, geom_ind).add(22, mat_ind);
cs.add(1, p->name_)
.add(10, p->geometries)
.add(11, p->materials)
.add(20, p->root_)
.add(21, geom_ind)
.add(23, mat_ind)
.add(24, p->cur_preset);
s << qCompress(cs.data());
return s;
}
@@ -525,7 +553,9 @@ QDataStream & operator>>(QDataStream & s, Scene *& p) {
s >> ba;
ba = qUncompress(ba);
ChunkStream cs(ba);
QVector<short> geom_ind, mat_ind;
QVector<short> geom_ind, mat_ind_v0;
QVector<QVector<short>> mat_ind_v1;
int version = 0, preset = 0;
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(p->name_); break;
@@ -536,16 +566,44 @@ QDataStream & operator>>(QDataStream & s, Scene *& p) {
p->root_->setScene(p);
break;
case 21: cs.get(geom_ind); break;
case 22: cs.get(mat_ind); break;
case 22:
cs.get(mat_ind_v0);
version = 0;
break;
case 23:
cs.get(mat_ind_v1);
version = 1;
break;
case 24: cs.get(preset); break;
}
}
p->makeMaterialsUniqueNames();
ObjectBaseList cl = p->root_->children(true);
int cnt = qMin(qMin(cl.size(), geom_ind.size()), mat_ind.size());
int cnt = qMin(cl.size(), geom_ind.size());
for (int i = 0; i < cnt; ++i) {
ObjectBase * c(cl[i]);
if (geom_ind[i] >= 0) c->mesh_ = p->geometries[geom_ind[i]];
if (mat_ind[i] >= 0) c->material_ = p->materials[mat_ind[i]];
}
if (version == 0) {
cnt = qMin(cl.size(), mat_ind_v0.size());
for (int i = 0; i < cnt; ++i) {
if (mat_ind_v0[i] >= 0) cl[i]->currentPreset().material = p->materials[mat_ind_v0[i]];
}
} else if (version == 1) {
cnt = qMin(cl.size(), mat_ind_v1.size());
for (int i = 0; i < cnt; ++i) {
ObjectBase * c(cl[i]);
const auto & matv(mat_ind_v1[i]);
if (c->presets.size() < matv.size()) c->presets.resize(matv.size());
for (int j = 0; j < matv.size(); ++j) {
if (matv[j] >= 0)
c->presets[j].material = p->materials[matv[j]];
else
c->presets[j].material = nullptr;
}
}
}
p->cur_preset = -1;
p->setPreset(preset);
return s;
}