------------------------------------------------------------------------------------------------
| 73 | |
| 74 | // ------------------------------------------------------------------------------------------------ |
| 75 | void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_data, const Scene &in, const Object &orig_object) { |
| 76 | size_t cnt = 0u, ful = 0u; |
| 77 | |
| 78 | // NOTE: this cast is potentially unsafe by design, so we need to perform type checks before |
| 79 | // we're allowed to dereference the pointers without risking to crash. We might still be |
| 80 | // invoking UB btw - we're assuming that the ModifierData member of the respective modifier |
| 81 | // structures is at offset sizeof(vftable) with no padding. |
| 82 | const SharedModifierData *cur = static_cast<const SharedModifierData *>(orig_object.modifiers.first.get()); |
| 83 | for (; cur; cur = static_cast<const SharedModifierData *>(cur->modifier.next.get()), ++ful) { |
| 84 | ai_assert(cur->dna_type); |
| 85 | |
| 86 | const Structure *s = conv_data.db.dna.Get(cur->dna_type); |
| 87 | if (!s) { |
| 88 | ASSIMP_LOG_WARN("BlendModifier: could not resolve DNA name: ", cur->dna_type); |
| 89 | continue; |
| 90 | } |
| 91 | |
| 92 | // this is a common trait of all XXXMirrorData structures in BlenderDNA |
| 93 | const Field *f = s->Get("modifier"); |
| 94 | if (!f || f->offset != 0) { |
| 95 | ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0"); |
| 96 | continue; |
| 97 | } |
| 98 | |
| 99 | s = conv_data.db.dna.Get(f->type); |
| 100 | if (!s || s->name != "ModifierData") { |
| 101 | ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member"); |
| 102 | continue; |
| 103 | } |
| 104 | |
| 105 | // now, we can be sure that we should be fine to dereference *cur* as |
| 106 | // ModifierData (with the above note). |
| 107 | const ModifierData &dat = cur->modifier; |
| 108 | |
| 109 | const fpCreateModifier *curgod = creators; |
| 110 | std::vector<BlenderModifier *>::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end(); |
| 111 | |
| 112 | for (; *curgod; ++curgod, ++curmod) { // allocate modifiers on the fly |
| 113 | if (curmod == endmod) { |
| 114 | cached_modifiers->push_back((*curgod)()); |
| 115 | |
| 116 | endmod = cached_modifiers->end(); |
| 117 | curmod = endmod - 1; |
| 118 | } |
| 119 | |
| 120 | BlenderModifier *const modifier = *curmod; |
| 121 | if (modifier->IsActive(dat)) { |
| 122 | modifier->DoIt(out, conv_data, *static_cast<const ElemBase *>(cur), in, orig_object); |
| 123 | cnt++; |
| 124 | |
| 125 | curgod = nullptr; |
| 126 | break; |
| 127 | } |
| 128 | } |
| 129 | if (curgod) { |
| 130 | ASSIMP_LOG_WARN("Couldn't find a handler for modifier: ", dat.name); |
| 131 | } |
| 132 | } |