History

fix crash in butterflies.js

ZappoMan committed 12 years ago

Commit ffe1e2d1 parent d01b73b6 files · +167 −45Browse files

Showing the changes to libraries/entities/src/UpdateEntityOperator.cpp (1 of 6 files). Show all

Unified · Split

libraries/entities/src/UpdateEntityOperator.cpp+121−21
@@ -36,6 +36,10 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, · 35 unmodified lines
36{36{
37 // caller must have verified existence of containingElement and oldEntity37 // caller must have verified existence of containingElement and oldEntity
38 assert(_containingElement && _existingEntity);38 assert(_containingElement && _existingEntity);
39
40 if (_wantDebug) {
41 qDebug() << "UpdateEntityOperator::UpdateEntityOperator() -----------------------------";
42 }
39 43
40 // Here we have a choice to make, do we want to "tight fit" the actual minimum for the44 // Here we have a choice to make, do we want to "tight fit" the actual minimum for the
41 // entity into the the element, or do we want to use the entities "relaxed" bounds45 // entity into the the element, or do we want to use the entities "relaxed" bounds
@@ -50,10 +54,19 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, · 8 unmodified lines
50 if (_properties.containsPositionChange() && !_properties.containsDimensionsChange()) {54 if (_properties.containsPositionChange() && !_properties.containsDimensionsChange()) {
51 glm::vec3 oldDimensionsInMeters = _existingEntity->getDimensions() * (float)TREE_SCALE;55 glm::vec3 oldDimensionsInMeters = _existingEntity->getDimensions() * (float)TREE_SCALE;
52 _properties.setDimensions(oldDimensionsInMeters);56 _properties.setDimensions(oldDimensionsInMeters);
57
58 if (_wantDebug) {
59 qDebug() << " ** setting properties dimensions - had position change, no dimension change **";
60 }
61
53 }62 }
54 if (!_properties.containsPositionChange() && _properties.containsDimensionsChange()) {63 if (!_properties.containsPositionChange() && _properties.containsDimensionsChange()) {
55 glm::vec3 oldPositionInMeters = _existingEntity->getPosition() * (float)TREE_SCALE;64 glm::vec3 oldPositionInMeters = _existingEntity->getPosition() * (float)TREE_SCALE;
56 _properties.setPosition(oldPositionInMeters);65 _properties.setPosition(oldPositionInMeters);
66
67 if (_wantDebug) {
68 qDebug() << " ** setting properties position - had dimensions change, no position change **";
69 }
57 }70 }
58 71
59 // If our new properties don't have bounds details (no change to position, etc) or if this containing element would 72 // If our new properties don't have bounds details (no change to position, etc) or if this containing element would
@@ -64,6 +77,11 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, · 4 unmodified lines
64 // if we don't have bounds properties, then use our old clamped box to determine best fit77 // if we don't have bounds properties, then use our old clamped box to determine best fit
65 if (!_properties.containsBoundsProperties()) {78 if (!_properties.containsBoundsProperties()) {
66 oldElementBestFit = _containingElement->bestFitBounds(_oldEntityBox);79 oldElementBestFit = _containingElement->bestFitBounds(_oldEntityBox);
80
81 if (_wantDebug) {
82 qDebug() << " ** old Element best fit - no dimensions change, no position change **";
83 }
84
67 }85 }
68 86
69 // For some reason we've seen a case where the original containing element isn't a best fit for the old properties87 // For some reason we've seen a case where the original containing element isn't a best fit for the old properties
@@ -71,20 +89,36 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, · 1 unmodified line
71 if (!_properties.containsBoundsProperties() && !oldElementBestFit) {89 if (!_properties.containsBoundsProperties() && !oldElementBestFit) {
72 _newEntityCube = _oldEntityCube;90 _newEntityCube = _oldEntityCube;
73 _removeOld = true; // our properties are going to move us, so remember this for later processing91 _removeOld = true; // our properties are going to move us, so remember this for later processing
92
93 if (_wantDebug) {
94 qDebug() << " **** UNUSUAL CASE **** no changes, but not best fit... consider it a move.... **";
95 }
96
97
74 } else if (!_properties.containsBoundsProperties() || oldElementBestFit) {98 } else if (!_properties.containsBoundsProperties() || oldElementBestFit) {
75 _foundOld = true;99 _foundOld = true;
76 _newEntityCube = _oldEntityCube;100 _newEntityCube = _oldEntityCube;
77 _dontMove = true;101 _dontMove = true;
102
103 if (_wantDebug) {
104 qDebug() << " **** TYPICAL NO MOVE CASE ****";
105 qDebug() << " _properties.containsBoundsProperties():" << _properties.containsBoundsProperties();
106 qDebug() << " oldElementBestFit:" << oldElementBestFit;
107 }
108
78 } else {109 } else {
79 _newEntityCube = _properties.getMaximumAACubeInTreeUnits();110 _newEntityCube = _properties.getMaximumAACubeInTreeUnits();
80 _removeOld = true; // our properties are going to move us, so remember this for later processing111 _removeOld = true; // our properties are going to move us, so remember this for later processing
112
113 if (_wantDebug) {
114 qDebug() << " **** TYPICAL MOVE CASE ****";
115 }
81 }116 }
82 117
83 _newEntityBox = _newEntityCube.clamp(0.0f, 1.0f); // clamp to domain bounds118 _newEntityBox = _newEntityCube.clamp(0.0f, 1.0f); // clamp to domain bounds
84 119
85 120
86 if (_wantDebug) {121 if (_wantDebug) {
87 qDebug() << "UpdateEntityOperator::UpdateEntityOperator() -----------------------------";
88 qDebug() << " _entityItemID:" << _entityItemID;122 qDebug() << " _entityItemID:" << _entityItemID;
89 qDebug() << " _containingElementCube:" << _containingElementCube;123 qDebug() << " _containingElementCube:" << _containingElementCube;
90 qDebug() << " _oldEntityCube:" << _oldEntityCube;124 qDebug() << " _oldEntityCube:" << _oldEntityCube;
@@ -108,31 +142,30 @@ bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) { · 17 unmodified lines
108 // so when we're searching the tree for the old element, we use the known cube for the known containing element142 // so when we're searching the tree for the old element, we use the known cube for the known containing element
109 bool elementContainsOldBox = element->getAACube().contains(_containingElementCube);143 bool elementContainsOldBox = element->getAACube().contains(_containingElementCube);
110 144
111 /*145 if (_wantDebug) {
112 bool elementContainsOldCube = element->getAACube().contains(_oldEntityCube);146 bool elementContainsOldCube = element->getAACube().contains(_oldEntityCube);
113 qDebug() << "UpdateEntityOperator::subTreeContainsOldEntity()....";147 qDebug() << "UpdateEntityOperator::subTreeContainsOldEntity()....";
114 qDebug() << " element->getAACube()=" << element->getAACube();148 qDebug() << " element->getAACube()=" << element->getAACube();
115 qDebug() << " _oldEntityCube=" << _oldEntityCube;149 qDebug() << " _oldEntityCube=" << _oldEntityCube;
116 qDebug() << " _oldEntityBox=" << _oldEntityBox;150 qDebug() << " _oldEntityBox=" << _oldEntityBox;
117 qDebug() << " elementContainsOldCube=" << elementContainsOldCube;151 qDebug() << " elementContainsOldCube=" << elementContainsOldCube;
118 qDebug() << " elementContainsOldBox=" << elementContainsOldBox;152 qDebug() << " elementContainsOldBox=" << elementContainsOldBox;
119 */153 }
120
121 return elementContainsOldBox;154 return elementContainsOldBox;
122}155}
123 156
124bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) {157bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) {
125 bool elementContainsNewBox = element->getAACube().contains(_newEntityBox);158 bool elementContainsNewBox = element->getAACube().contains(_newEntityBox);
126 159
127 /*160 if (_wantDebug) {
128 bool elementContainsNewCube = element->getAACube().contains(_newEntityCube);161 bool elementContainsNewCube = element->getAACube().contains(_newEntityCube);
129 qDebug() << "UpdateEntityOperator::subTreeContainsNewEntity()....";162 qDebug() << "UpdateEntityOperator::subTreeContainsNewEntity()....";
130 qDebug() << " element->getAACube()=" << element->getAACube();163 qDebug() << " element->getAACube()=" << element->getAACube();
131 qDebug() << " _newEntityCube=" << _newEntityCube;164 qDebug() << " _newEntityCube=" << _newEntityCube;
132 qDebug() << " _newEntityBox=" << _newEntityBox;165 qDebug() << " _newEntityBox=" << _newEntityBox;
133 qDebug() << " elementContainsNewCube=" << elementContainsNewCube;166 qDebug() << " elementContainsNewCube=" << elementContainsNewCube;
134 qDebug() << " elementContainsNewBox=" << elementContainsNewBox;167 qDebug() << " elementContainsNewBox=" << elementContainsNewBox;
135 */168 }
136 169
137 return elementContainsNewBox;170 return elementContainsNewBox;
138}171}
@@ -155,18 +188,42 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { · 16 unmodified lines
155 bool subtreeContainsOld = subTreeContainsOldEntity(element);188 bool subtreeContainsOld = subTreeContainsOldEntity(element);
156 bool subtreeContainsNew = subTreeContainsNewEntity(element);189 bool subtreeContainsNew = subTreeContainsNewEntity(element);
157 190
191 if (_wantDebug) {
192 qDebug() << "---- UpdateEntityOperator::preRecursion().... ----";
193 qDebug() << " element=" << element->getAACube();
194 qDebug() << " subtreeContainsOld=" << subtreeContainsOld;
195 qDebug() << " subtreeContainsNew=" << subtreeContainsNew;
196 qDebug() << " _foundOld=" << _foundOld;
197 qDebug() << " _foundNew=" << _foundNew;
198 }
199
158 // If we haven't yet found the old entity, and this subTreeContains our old200 // If we haven't yet found the old entity, and this subTreeContains our old
159 // entity, then we need to keep searching.201 // entity, then we need to keep searching.
160 if (!_foundOld && subtreeContainsOld) {202 if (!_foundOld && subtreeContainsOld) {
161 203
204 if (_wantDebug) {
205 qDebug() << " OLD TREE CASE....";
206 qDebug() << " entityTreeElement=" << entityTreeElement;
207 qDebug() << " _containingElement=" << _containingElement;
208 }
209
162 // If this is the element we're looking for, then ask it to remove the old entity210 // If this is the element we're looking for, then ask it to remove the old entity
163 // and we can stop searching.211 // and we can stop searching.
164 if (entityTreeElement == _containingElement) {212 if (entityTreeElement == _containingElement) {
165 213
214 if (_wantDebug) {
215 qDebug() << " *** it's the OLD ELEMENT! ***";
216 }
217
166 // If the containgElement IS NOT the best fit for the new entity properties218 // If the containgElement IS NOT the best fit for the new entity properties
167 // then we need to remove it, and the updateEntity below will store it in the219 // then we need to remove it, and the updateEntity below will store it in the
168 // correct element.220 // correct element.
169 if (_removeOld) {221 if (_removeOld) {
222
223 if (_wantDebug) {
224 qDebug() << " *** REMOVING from ELEMENT ***";
225 }
226
170 entityTreeElement->removeEntityItem(_existingEntity); // NOTE: only removes the entity, doesn't delete it227 entityTreeElement->removeEntityItem(_existingEntity); // NOTE: only removes the entity, doesn't delete it
171 228
172 // If we haven't yet found the new location, then we need to 229 // If we haven't yet found the new location, then we need to
@@ -174,6 +231,11 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { · 1 unmodified line
174 // now we're not in that map231 // now we're not in that map
175 if (!_foundNew) {232 if (!_foundNew) {
176 _tree->setContainingElement(_entityItemID, NULL);233 _tree->setContainingElement(_entityItemID, NULL);
234
235 if (_wantDebug) {
236 qDebug() << " *** REMOVING from MAP ***";
237 }
238
177 }239 }
178 }240 }
179 _foundOld = true;241 _foundOld = true;
@@ -187,11 +249,27 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { · 7 unmodified lines
187 // entity, then we need to keep searching.249 // entity, then we need to keep searching.
188 if (!_foundNew && subtreeContainsNew) {250 if (!_foundNew && subtreeContainsNew) {
189 251
252 if (_wantDebug) {
253 qDebug() << " NEW TREE CASE....";
254 qDebug() << " entityTreeElement=" << entityTreeElement;
255 qDebug() << " _containingElement=" << _containingElement;
256 qDebug() << " entityTreeElement->bestFitBounds(_newEntityBox)=" << entityTreeElement->bestFitBounds(_newEntityBox);
257 }
258
259
190 // If this element is the best fit for the new entity properties, then add/or update it260 // If this element is the best fit for the new entity properties, then add/or update it
191 if (entityTreeElement->bestFitBounds(_newEntityBox)) {261 if (entityTreeElement->bestFitBounds(_newEntityBox)) {
192 262
263 if (_wantDebug) {
264 qDebug() << " *** THIS ELEMENT IS BEST FIT ***";
265 }
266
193 // if we are the existing containing element, then we can just do the update of the entity properties267 // if we are the existing containing element, then we can just do the update of the entity properties
194 if (entityTreeElement == _containingElement) {268 if (entityTreeElement == _containingElement) {
269
270 if (_wantDebug) {
271 qDebug() << " *** This is the same OLD ELEMENT ***";
272 }
195 273
196 // TODO: We shouldn't be in a remove old case and also be the new best fit. This indicates that274 // TODO: We shouldn't be in a remove old case and also be the new best fit. This indicates that
197 // we have some kind of a logic error in this operator. But, it can handle it properly by setting275 // we have some kind of a logic error in this operator. But, it can handle it properly by setting
@@ -201,21 +279,43 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { · 3 unmodified lines
201 qDebug() << "UNEXPECTED - UpdateEntityOperator - "279 qDebug() << "UNEXPECTED - UpdateEntityOperator - "
202 "we thought we needed to removeOld, but the old entity is our best fit.";280 "we thought we needed to removeOld, but the old entity is our best fit.";
203 _removeOld = false;281 _removeOld = false;
282
283 // if we thought we were supposed to remove the old item, and we already did, then we need
284 // to repair this case.
285 if (_foundOld) {
286 if (_wantDebug) {
287 qDebug() << " *** REPAIRING PREVIOUS REMOVAL from ELEMENT and MAP ***";
288 }
289 entityTreeElement->addEntityItem(_existingEntity);
290 _tree->setContainingElement(_entityItemID, entityTreeElement);
291 }
204 }292 }
205 293
206 // set the entity properties and mark our element as changed.294 // set the entity properties and mark our element as changed.
207 _existingEntity->setProperties(_properties);295 _existingEntity->setProperties(_properties);
296 if (_wantDebug) {
297 qDebug() << " *** set properties ***";
298 }
208 } else {299 } else {
209 // otherwise, this is an add case.300 // otherwise, this is an add case.
210 entityTreeElement->addEntityItem(_existingEntity);301 entityTreeElement->addEntityItem(_existingEntity);
211 _existingEntity->setProperties(_properties); // still need to update the properties!302 _existingEntity->setProperties(_properties); // still need to update the properties!
212 _tree->setContainingElement(_entityItemID, entityTreeElement);303 _tree->setContainingElement(_entityItemID, entityTreeElement);
304 if (_wantDebug) {
305 qDebug() << " *** ADDING ENTITY to ELEMENT and MAP and SETTING PROPERTIES ***";
306 }
213 }307 }
214 _foundNew = true; // we found the new item!308 _foundNew = true; // we found the new item!
215 } else {309 } else {
216 keepSearching = true;310 keepSearching = true;
217 }311 }
218 }312 }
313
314 if (_wantDebug) {
315 qDebug() << " FINAL --- keepSearching=" << keepSearching;
316 qDebug() << "--------------------------------------------------";
317 }
318
219 319
220 return keepSearching; // if we haven't yet found it, keep looking320 return keepSearching; // if we haven't yet found it, keep looking
221}321}