Ticket #914: selection_bbox_26sep11.patch
File selection_bbox_26sep11.patch, 44.2 KB (added by , 13 years ago) |
---|
-
binaries/data/mods/public/gui/session/session.xml
diff --git a/binaries/data/mods/public/gui/session/session.xml b/binaries/data/mods/public/gui/session/session.xml index d7cb414..1534c2a 100644
a b 89 89 /> 90 90 91 91 <!-- Dev/cheat commands --> 92 <object name="devCommands" size="100%-156 50%-8 0 100%-8 50%+80" type="image" sprite="devCommandsBackground"92 <object name="devCommands" size="100%-156 50%-88 100%-8 50%+88" type="image" sprite="devCommandsBackground" 93 93 hidden="true" hotkey="session.devcommands.toggle"> 94 94 <action on="Press"> 95 95 toggleDeveloperOverlay(); … … 126 126 <action on="Press">Engine.GuiInterfaceCall("SetRangeDebugOverlay", this.checked);</action> 127 127 </object> 128 128 129 <object size="0 96 100%-18 112" type="text" style="devCommandsText">Restrict camera</object> 130 <object size="100%-16 96 100% 112" type="checkbox" style="StoneCrossBox" checked="true"> 129 <object size="0 96 100%-18 112" type="text" style="devCommandsText">Bounding box overlay</object> 130 <object size="100%-16 96 100% 112" type="checkbox" style="StoneCrossBox"> 131 <action on="Press">Engine.SetBoundingBoxDebugOverlay(this.checked);</action> 132 </object> 133 134 <object size="0 112 100%-18 128" type="text" style="devCommandsText">Restrict camera</object> 135 <object size="100%-16 112 100% 128" type="checkbox" style="StoneCrossBox" checked="true"> 131 136 <action on="Press">gameView.constrainCamera = this.checked;</action> 132 137 </object> 133 138 134 <object size="0 1 12 100%-18 128" type="text" style="devCommandsText">Reveal map</object>135 <object name="devCommandsRevealMap" size="100%-16 112 100% 128" type="checkbox" style="StoneCrossBox">139 <object size="0 128 100%-18 144" type="text" style="devCommandsText">Reveal map</object> 140 <object size="100%-16 128 100% 144" type="checkbox" name="devCommandsRevealMap" style="StoneCrossBox"> 136 141 <action on="Press">Engine.PostNetworkCommand({"type": "reveal-map", "enable": this.checked});</action> 137 142 </object> 138 143 139 <object size="0 1 28 100%-18 144" type="text" style="devCommandsText">Enable time warp</object>140 <object size="100%-16 1 28 100% 144" type="checkbox" name="devTimeWarp" style="StoneCrossBox">144 <object size="0 144 100%-18 160" type="text" style="devCommandsText">Enable time warp</object> 145 <object size="100%-16 144 100% 160" type="checkbox" name="devTimeWarp" style="StoneCrossBox"> 141 146 <action on="Press">Engine.EnableTimeWarpRecording(this.checked ? 10 : 0);</action> 142 147 </object> 143 148 144 <object size="0 1 44 100%-18 160" type="text" style="devCommandsText">Promote selected units</object>145 <object size="100%-16 1 44 100% 160" type="button" style="StoneCrossBox">149 <object size="0 160 100%-18 176" type="text" style="devCommandsText">Promote selected units</object> 150 <object size="100%-16 160 100% 176" type="button" style="StoneCrossBox"> 146 151 <action on="Press">Engine.PostNetworkCommand({"type": "promote", "entities": g_Selection.toList()});</action> 147 152 </object> 148 153 </object> -
source/graphics/GameView.cpp
diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp index 7e17a4a..4e8205c 100644
a b void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c) 493 493 CPatch* patch=pTerrain->GetPatch(i,j); // can't fail 494 494 495 495 // If the patch is underwater, calculate a bounding box that also contains the water plane 496 CBound bounds = patch->Get Bounds();496 CBound bounds = patch->GetWorldBounds(); 497 497 float waterHeight = g_Renderer.GetWaterManager()->m_WaterHeight + 0.001f; 498 498 if(bounds[1].Y < waterHeight) { 499 499 bounds[1].Y = waterHeight; -
source/graphics/Model.cpp
diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index 704e2b2..0ac99be 100644
a b void CModel::CalcBounds() 116 116 if (! (m_Anim && m_Anim->m_AnimDef)) 117 117 { 118 118 if (m_ObjectBounds.IsEmpty()) 119 Calc ObjectBounds();119 CalcStaticObjectBounds(); 120 120 } 121 121 else 122 122 { 123 123 if (m_Anim->m_ObjectBounds.IsEmpty()) 124 CalcAnimatedObjectBound (m_Anim->m_AnimDef, m_Anim->m_ObjectBounds);124 CalcAnimatedObjectBounds(m_Anim->m_AnimDef, m_Anim->m_ObjectBounds); 125 125 ENSURE(! m_Anim->m_ObjectBounds.IsEmpty()); // (if this happens, it'll be recalculating the bounds every time) 126 126 m_ObjectBounds = m_Anim->m_ObjectBounds; 127 127 } … … void CModel::CalcBounds() 129 129 // Ensure the transform is set correctly before we use it 130 130 ValidatePosition(); 131 131 132 // Now transform the object-space bounds to world-space bounds 132 133 m_ObjectBounds.Transform(GetTransform(), m_Bounds); 133 134 } 134 135 135 136 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 136 137 // CalcObjectBounds: calculate object space bounds of this model, based solely on vertex positions 137 void CModel::Calc ObjectBounds()138 void CModel::CalcStaticObjectBounds() 138 139 { 139 140 m_ObjectBounds.SetEmpty(); 140 141 141 size_t num verts=m_pModelDef->GetNumVertices();142 SModelVertex* verts =m_pModelDef->GetVertices();142 size_t numVerts = m_pModelDef->GetNumVertices(); 143 SModelVertex* verts = m_pModelDef->GetVertices(); 143 144 144 for (size_t i =0;i<numverts;i++) {145 m_ObjectBounds +=verts[i].m_Coords;145 for (size_t i = 0; i < numVerts; i++) { 146 m_ObjectBounds += verts[i].m_Coords; 146 147 } 147 148 } 148 149 149 150 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 150 151 // CalcAnimatedObjectBound: calculate bounds encompassing all vertex positions for given animation 151 void CModel::CalcAnimatedObjectBound (CSkeletonAnimDef* anim,CBound& result)152 void CModel::CalcAnimatedObjectBounds(CSkeletonAnimDef* anim, CBound& result) 152 153 { 153 154 result.SetEmpty(); 154 155 155 156 // Set the current animation on which to perform calculations (if it's necessary) 156 157 if (anim != m_Anim->m_AnimDef) 157 158 { 158 CSkeletonAnim dummy anim;159 dummy anim.m_AnimDef=anim;160 if (!SetAnimation(&dummy anim)) return;159 CSkeletonAnim dummyAnim; 160 dummyAnim.m_AnimDef = anim; 161 if (!SetAnimation(&dummyAnim)) return; 161 162 } 162 163 163 size_t num verts=m_pModelDef->GetNumVertices();164 SModelVertex* vert s=m_pModelDef->GetVertices();164 size_t numVertices = m_pModelDef->GetNumVertices(); 165 SModelVertex* vertices = m_pModelDef->GetVertices(); 165 166 166 167 // Remove any transformations, so that we calculate the bounding box 167 168 // at the origin. The box is later re-transformed onto the object, without 168 169 // having to recalculate the size of the box. 169 CMatrix3D transform, old transform = GetTransform();170 CModelAbstract* old parent = m_Parent;170 CMatrix3D transform, oldTransform = GetTransform(); 171 CModelAbstract* oldParent = m_Parent; 171 172 172 173 m_Parent = 0; 173 174 transform.SetIdentity(); … … void CModel::CalcAnimatedObjectBound(CSkeletonAnimDef* anim,CBound& result) 179 180 float AnimTime = m_AnimTime; 180 181 181 182 // iterate through every frame of the animation 182 for (size_t j=0;j<anim->GetNumFrames();j++) { 183 for (size_t j = 0; j < anim->GetNumFrames(); j++) 184 { 183 185 m_PositionValid = false; 184 186 ValidatePosition(); 185 187 186 188 // extend bounds by vertex positions at the frame 187 for (size_t i =0;i<numverts;i++)189 for (size_t i = 0; i < numVertices; i++) 188 190 { 189 result += CModelDef::SkinPoint(vert s[i], GetAnimatedBoneMatrices());191 result += CModelDef::SkinPoint(vertices[i], GetAnimatedBoneMatrices()); 190 192 } 191 193 // advance to next frame 192 194 m_AnimTime += anim->GetFrameTime(); 193 195 } 194 196 195 197 m_PositionValid = false; 196 m_Parent = old parent;197 SetTransform(old transform);198 m_Parent = oldParent; 199 SetTransform(oldTransform); 198 200 m_AnimTime = AnimTime; 199 201 } 200 202 201 203 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 202 const CBound CModel::Get BoundsRec()204 const CBound CModel::GetWorldBoundsRec() 203 205 { 204 CBound bounds = Get Bounds();206 CBound bounds = GetWorldBounds(); 205 207 for (size_t i = 0; i < m_Props.size(); ++i) 206 bounds += m_Props[i].m_Model->Get BoundsRec();208 bounds += m_Props[i].m_Model->GetWorldBoundsRec(); 207 209 return bounds; 208 210 } 209 211 212 const CBound CModel::GetObjectSelectionBoundsRec() 213 { 214 CBound objBounds = GetObjectBounds(); // updates the (children-not-included) object-space bounds if necessary 215 216 // now extend these bounds to include the submodels' selection bounds (if any) 217 for (size_t i = 0; i < m_Props.size(); ++i) 218 { 219 CBound propSelectionBounds = m_Props[i].m_Model->GetObjectSelectionBoundsRec(); 220 if (propSelectionBounds.IsEmpty()) 221 continue; // submodel does not wish to participate in selection box, exclude it 222 223 // Translate the prop's selection bounds to the prop position within this model 224 CBound relativePropSelectionBounds( 225 m_Props[i].m_Point->m_Position + propSelectionBounds[0], 226 m_Props[i].m_Point->m_Position + propSelectionBounds[1] 227 ); 228 objBounds += relativePropSelectionBounds; 229 } 230 231 return objBounds; 232 } 233 210 234 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 211 235 // BuildAnimation: load raw animation frame animation from given file, and build a 212 236 // animation specific to this model -
source/graphics/Model.h
diff --git a/source/graphics/Model.h b/source/graphics/Model.h index 84efeb6..9f43ba2 100644
a b public: 75 75 76 76 // setup model from given geometry 77 77 bool InitModel(const CModelDefPtr& modeldef); 78 // calculate the world space bounds of this model79 virtual void CalcBounds();80 78 // update this model's state; 'time' is the absolute time since the start of the animation, in MS 81 79 void UpdateTo(float time); 82 80 … … public: 133 131 m_Props[i].m_Model->SetEntityVariable(name, value); 134 132 } 135 133 136 // calculate object space bounds of this model, based solely on vertex positions 137 void CalcObjectBounds(); 138 // calculate bounds encompassing all vertex positions for given animation 139 void CalcAnimatedObjectBound(CSkeletonAnimDef* anim,CBound& result); 134 // --- WORLD/OBJECT SPACE BOUNDS ----------------------------------------------------------------- 135 136 /// Overridden to calculate both the world-space and object-space bounds of this model, and stores the result in 137 /// m_Bounds and m_ObjectBounds, respectively. 138 virtual void CalcBounds(); 139 140 /// Returns the object-space bounds for this model, excluding its children. 141 const CBound& GetObjectBounds() 142 { 143 RecalculateBoundsIfNecessary(); // recalculates both object-space and world-space bounds if necessary 144 return m_ObjectBounds; 145 } 146 147 virtual const CBound GetWorldBoundsRec(); // reimplemented here 140 148 141 virtual const CBound GetBoundsRec(); 149 /// Auxiliary method; calculates object space bounds of this model, based solely on vertex positions, and stores 150 /// the result in m_ObjectBounds. Called by CalcBounds (instead of CalcAnimatedObjectBounds) if it has been determined 151 /// that the object-space bounds are static. 152 void CalcStaticObjectBounds(); 153 /// Auxiliary method; calculate object-space bounds encompassing all vertex positions for given animation, and stores 154 /// the result in m_ObjectBounds. Called by CalcBounds (instead of CalcStaticBounds) if it has been determined that the 155 /// object-space bounds need to take animations into account. 156 void CalcAnimatedObjectBounds(CSkeletonAnimDef* anim,CBound& result); 157 158 // --- SELECTION BOX/BOUNDS ---------------------------------------------------------------------- 159 160 /// Reimplemented here since proper models should participate in selection boxes. 161 virtual const CBound GetObjectSelectionBoundsRec(); 142 162 143 163 /** 144 164 * Set transform of this object. … … private: 247 267 // list of current props on model 248 268 std::vector<Prop> m_Props; 249 269 250 /** 251 * The prop point to which the ammo prop is attached, or NULL if none 252 */ 270 /// The prop point to which the ammo prop is attached, or NULL if none 253 271 const SPropPoint* m_AmmoPropPoint; 254 272 255 /** 256 * If m_AmmoPropPoint is not NULL, then the index in m_Props of the ammo prop 257 */ 273 /// If m_AmmoPropPoint is not NULL, then the index in m_Props of the ammo prop 258 274 size_t m_AmmoLoadedProp; 259 275 260 // manager object which can load animations for us276 /// manager object which can load animations for us 261 277 CSkeletonAnimManager& m_SkeletonAnimManager; 262 278 }; 263 279 -
new file source/graphics/ModelAbstract.cpp
diff --git a/source/graphics/ModelAbstract.cpp b/source/graphics/ModelAbstract.cpp new file mode 100644 index 0000000..0953a88
- + 1 /* Copyright (C) 2011 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "ModelAbstract.h" 21 22 const CBox& CModelAbstract::GetSelectionBox() 23 { 24 if (!m_SelectionBoxValid) 25 { 26 CalcSelectionBox(); 27 m_SelectionBoxValid = true; 28 } 29 return m_SelectionBox; 30 } 31 32 void CModelAbstract::CalcSelectionBox() 33 { 34 // Get the object-space bounds that should be used to construct this model (and its children)'s selection box 35 CBound objBounds = GetObjectSelectionBoundsRec(); 36 if (objBounds.IsEmpty()) 37 { 38 m_SelectionBox.SetEmpty(); // model does not wish to participate in selection 39 return; 40 } 41 42 /// Prevent the bounding box from extending through the terrain; clip the lower plane at Y=0 in object space. 43 if (objBounds[1].Y > 0.f) // should always be the case, unless the models are defined really weirdly 44 objBounds[0].Y = std::max(0.f, objBounds[0].Y); 45 //objBounds[0].Y = 0; 46 47 // Take the box from object space, and transform it into a box in world space (i.e. an OBB) instead of a bound (i.e. an AABB). 48 CVector3D objCenter; 49 objBounds.GetCentre(objCenter); 50 51 const CMatrix3D& transform = GetTransform(); 52 53 // transform the object-space axis unit vectors to world space. Since this is basically multiplying the transformation matrix 54 // by the unity matrix, the result is the columns of the transformation matrix. We're not interested in translations for this, 55 // so just take the linear transform columns of the 4D transformations matrix. 56 CVector3D worldU(transform._11, transform._21, transform._31); 57 CVector3D worldV(transform._12, transform._22, transform._32); 58 CVector3D worldW(transform._13, transform._23, transform._33); 59 60 // after normalization, these should be mutually orthonormal (but e.g. during animations, they aren't always). 61 worldU.Normalize(); 62 worldV.Normalize(); 63 worldW.Normalize(); 64 65 m_SelectionBox.m_Center = objCenter + transform.GetTranslation(); // translated center position 66 m_SelectionBox.m_Basis[0] = worldU; 67 m_SelectionBox.m_Basis[1] = worldV; 68 m_SelectionBox.m_Basis[2] = worldW; 69 m_SelectionBox.m_HalfSizes = (objBounds[1] - objBounds[0]) * 0.5f; // element-wise subtraction and division by 2 70 71 ENSURE( m_SelectionBox.m_HalfSizes[0] >= 0.f 72 && m_SelectionBox.m_HalfSizes[1] >= 0.f 73 && m_SelectionBox.m_HalfSizes[2] >= 0.f); // must all be positive 74 } 75 No newline at end of file -
source/graphics/ModelAbstract.h
diff --git a/source/graphics/ModelAbstract.h b/source/graphics/ModelAbstract.h index 2c01968..9530a4a 100644
a b 18 18 #ifndef INCLUDED_MODELABSTRACT 19 19 #define INCLUDED_MODELABSTRACT 20 20 21 #include "maths/Box.h" 21 22 #include "graphics/RenderableObject.h" 22 23 #include "ps/Overlay.h" 23 24 #include "simulation2/helpers/Player.h" … … class CModelAbstract : public CRenderableObject 39 40 public: 40 41 CModelAbstract() : 41 42 m_Parent(NULL), m_PositionValid(false), 42 m_ShadingColor(1, 1, 1, 1), m_PlayerID(INVALID_PLAYER) 43 m_ShadingColor(1, 1, 1, 1), m_PlayerID(INVALID_PLAYER), m_SelectionBoxValid(false) 43 44 { 45 m_SelectionBox.SetEmpty(); 44 46 } 45 47 46 48 virtual CModelAbstract* Clone() const = 0; … … public: 58 60 // and this seems the easiest way to integrate with other code that wants 59 61 // type-specific processing) 60 62 61 /** 62 * Calls SetDirty on this model and all child objects. 63 */ 63 /// Calls SetDirty on this model and all child objects. 64 64 virtual void SetDirtyRec(int dirtyflags) = 0; 65 65 66 /// Returns world space bounds of this object and all child objects. 67 virtual const CBound GetWorldBoundsRec() { return GetWorldBounds(); } 68 66 69 /** 67 * Returns world space bounds of this object and all child objects. 70 * Returns the world-space selection box of this model. Used for selection ray hittesting. The returned selection box may be empty to indicate 71 * that it does not wish to participate in the selection process. 68 72 */ 69 virtual const CBound GetBoundsRec() { return GetBounds(); } 73 virtual const CBox& GetSelectionBox(); 74 75 void CalcSelectionBox(); 76 77 virtual void InvalidateBounds() { 78 m_BoundsValid = false; 79 m_SelectionBoxValid = false; // the selection boxes depend on the bounds, so we need to also invalidate them here 80 } 81 82 /// Returns the (object-space) bounds that should be used to construct a selection box for this model and its children. 83 /// May return an empty bound to indicate that this model and its children should not be selectable themselves, or should 84 /// not be included in its parent model's selection box. 85 /// If you wish your model type to be included in selection boxes, override this method and have it return the object-space 86 /// bounds of itself, augmented recursively (via this method) with the selection bounds from its children (if any). 87 virtual const CBound GetObjectSelectionBoundsRec() { return CBound::EMPTY; } 70 88 71 89 /** 72 90 * Called when terrain has changed in the given inclusive bounds. … … public: 100 118 virtual void SetShadingColor(const CColor& colour) { m_ShadingColor = colour; } 101 119 virtual CColor GetShadingColor() const { return m_ShadingColor; } 102 120 103 /// If non-null points to the model that we are attached to. 121 122 public: 123 /// If non-null, points to the model that we are attached to. 104 124 CModelAbstract* m_Parent; 105 125 106 126 /// True if both transform and and bone matrices are valid. … … public: 110 130 111 131 // modulating color 112 132 CColor m_ShadingColor; 133 134 protected: 135 /// Selection box for this model. 136 CBox m_SelectionBox; 137 /// Is the current selection box valid? 138 bool m_SelectionBoxValid; 139 113 140 }; 114 141 115 142 #endif // INCLUDED_MODELABSTRACT -
source/graphics/ObjectEntry.cpp
diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index 25054ab..069ea31 100644
a b bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections 129 129 model->SetTexture(texture); 130 130 131 131 // calculate initial object space bounds, based on vertex positions 132 model->Calc ObjectBounds();132 model->CalcStaticObjectBounds(); 133 133 134 134 // load the animations 135 135 for (std::multimap<CStr, CObjectBase::Anim>::iterator it = variation.anims.begin(); it != variation.anims.end(); ++it) -
source/graphics/RenderableObject.h
diff --git a/source/graphics/RenderableObject.h b/source/graphics/RenderableObject.h index 1b642f8..2fa3667 100644
a b public: 68 68 if (m_Transform == transform) 69 69 return; 70 70 // store transform, calculate inverse 71 m_Transform =transform;71 m_Transform = transform; 72 72 m_Transform.GetInverse(m_InvTransform); 73 73 // normal recalculation likely required on transform change; flag it 74 74 SetDirty(RENDERDATA_UPDATE_VERTICES); … … public: 86 86 if (m_RenderData) m_RenderData->m_UpdateFlags|=dirtyflags; 87 87 } 88 88 89 // calculate (and store in m_Bounds) the world space bounds of this object 90 // - must be implemented by all concrete subclasses 89 /// Calculate (and store) any bounds or bound-dependent data for this object. At this level, this is only the world-space bounds stored 90 /// in m_Bounds; subclasses may use this method to compute additional bounds if necessary (or any data that depends on the bounds). 91 /// Whenever bound-dependent data is requested through a public interface, RecalculateBoundsIfNecessary should be called to ensure 92 /// bound correctness, which will in turn call this method. 91 93 virtual void CalcBounds() = 0; 92 94 93 95 // return world space bounds of this object 94 const CBound& GetBounds() { 95 if (! m_BoundsValid) { 96 CalcBounds(); 97 m_BoundsValid = true; 98 } 96 const CBound& GetWorldBounds() { 97 RecalculateBoundsIfNecessary(); 99 98 return m_Bounds; 100 99 } 101 100 102 v oid InvalidateBounds() { m_BoundsValid = false; }101 virtual void InvalidateBounds() { m_BoundsValid = false; } 103 102 104 103 // Set the object renderdata and free previous renderdata, if any. 105 104 void SetRenderData(CRenderData* renderdata) { … … public: 112 111 CRenderData* GetRenderData() { return m_RenderData; } 113 112 114 113 protected: 114 /// Factored out so subclasses don't need to repeat this if they want to add additional getters for bounds-related methods 115 /// (since they'll have to make sure to recalc the bounds if necessary before they return it). 116 void RecalculateBoundsIfNecessary() 117 { 118 if (!m_BoundsValid) { 119 CalcBounds(); 120 m_BoundsValid = true; 121 } 122 } 123 124 protected: 115 125 // object bounds 116 126 CBound m_Bounds; 117 127 // local->world space transform … … protected: 120 130 CMatrix3D m_InvTransform; 121 131 // object renderdata 122 132 CRenderData* m_RenderData; 123 124 private:125 133 // remembers whether m_bounds needs to be recalculated 126 134 bool m_BoundsValid; 127 135 }; -
source/graphics/UnitManager.cpp
diff --git a/source/graphics/UnitManager.cpp b/source/graphics/UnitManager.cpp index d8604fe..0e3d7d1 100644
a b CUnit* CUnitManager::PickUnit(const CVector3D& origin, const CVector3D& dir) con 100 100 CUnit* unit = m_Units[i]; 101 101 float tmin, tmax; 102 102 103 if (unit->GetModel().Get Bounds().RayIntersect(origin, dir, tmin, tmax))103 if (unit->GetModel().GetWorldBounds().RayIntersect(origin, dir, tmin, tmax)) 104 104 { 105 105 // Point of closest approach 106 106 CVector3D obj; 107 unit->GetModel().Get Bounds().GetCentre(obj);107 unit->GetModel().GetWorldBounds().GetCentre(obj); 108 108 CVector3D delta = obj - origin; 109 109 float distance = delta.Dot(dir); 110 110 CVector3D closest = origin + dir * distance; -
source/gui/scripting/ScriptFunctions.cpp
diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp index 0054246..d64fae2 100644
a b 48 48 #include "simulation2/components/ICmpGuiInterface.h" 49 49 #include "simulation2/components/ICmpRangeManager.h" 50 50 #include "simulation2/components/ICmpTemplateManager.h" 51 #include "simulation2/components/ICmpSelectable.h" 51 52 #include "simulation2/helpers/Selection.h" 52 53 53 54 #include "js/jsapi.h" … … void RewindTimeWarp(void* UNUSED(cbdata)) 456 457 g_Game->GetTurnManager()->RewindTimeWarp(); 457 458 } 458 459 460 void SetBoundingBoxDebugOverlay(void* UNUSED(cbdata), bool enabled) 461 { 462 ICmpSelectable::s_EnableDebugOverlays = enabled; 463 } 464 459 465 } // namespace 460 466 461 467 void GuiScriptingInit(ScriptInterface& scriptInterface) … … void GuiScriptingInit(ScriptInterface& scriptInterface) 520 526 scriptInterface.RegisterFunction<void, &DumpSimState>("DumpSimState"); 521 527 scriptInterface.RegisterFunction<void, unsigned int, &EnableTimeWarpRecording>("EnableTimeWarpRecording"); 522 528 scriptInterface.RegisterFunction<void, &RewindTimeWarp>("RewindTimeWarp"); 529 scriptInterface.RegisterFunction<void, bool, &SetBoundingBoxDebugOverlay>("SetBoundingBoxDebugOverlay"); 523 530 } -
source/maths/Bound.cpp
diff --git a/source/maths/Bound.cpp b/source/maths/Bound.cpp index bf6d798..4213a63 100644
a b 32 32 #include "maths/Matrix3D.h" 33 33 34 34 35 const CBound CBound::EMPTY = CBound(); // initializes to an empty bound 36 35 37 /////////////////////////////////////////////////////////////////////////////// 36 38 // RayIntersect: intersect ray with this bound; return true 37 39 // if ray hits (and store entry and exit times), or false -
source/maths/Bound.h
diff --git a/source/maths/Bound.h b/source/maths/Bound.h index 7a22eee..ee0bf81 100644
a b 16 16 */ 17 17 18 18 /* 19 * Axis-aligned bounding box 19 * Axis-aligned bounding box (AABB) 20 20 */ 21 21 22 22 #ifndef INCLUDED_BOUND … … class CFrustum; 29 29 class CMatrix3D; 30 30 31 31 /////////////////////////////////////////////////////////////////////////////// 32 // CBound: basic axis aligned bounding box class 32 // CBound: basic axis aligned bounding box class (AABB) 33 33 class CBound 34 34 { 35 35 public: 36 36 37 CBound() { SetEmpty(); } 37 CBound(const CVector3D& min,const CVector3D& max) { 38 m_Data[0]=min; m_Data[1]=max; 38 CBound(const CVector3D& min, const CVector3D& max) { 39 m_Data[0] = min; 40 m_Data[1] = max; 39 41 } 40 42 41 void Transform(const CMatrix3D& m, CBound& result) const;43 void Transform(const CMatrix3D& m, CBound& result) const; 42 44 43 45 CVector3D& operator[](int index) { return m_Data[index]; } 44 46 const CVector3D& operator[](int index) const { return m_Data[index]; } … … public: 70 72 return *this; 71 73 } 72 74 73 bool RayIntersect(const CVector3D& origin,const CVector3D& dir,float& tmin,float& tmax) const; 75 /** 76 * Returns true if the ray originating in @p origin and with unit direction vector @p dir intersects this AABB, false otherwise. 77 * Additionally, returns the positive distances from the origin of the ray to the entry and exit points in the bounding box in 78 * @p tmin and @p tmax. See also Real-Time Rendering, Third Edition by T. Akenine-Möller, p. 741--742. 79 * @param origin Origin of the ray. 80 * @param dir Direction vector of the ray. Must be of unit length. 81 */ 82 bool RayIntersect(const CVector3D& origin, const CVector3D& dir, float& tmin, float& tmax) const; 74 83 75 84 // return the volume of this bounding box 76 float GetVolume() const { 77 CVector3D v=m_Data[1]-m_Data[0]; 78 return std::max(v.X, 0.0f)*std::max(v.Y, 0.0f)*std::max(v.Z, 0.0f); 85 float GetVolume() const 86 { 87 CVector3D v = m_Data[1] - m_Data[0]; 88 return (std::max(v.X, 0.0f) * std::max(v.Y, 0.0f) * std::max(v.Z, 0.0f)); 79 89 } 80 90 81 91 // return the centre of this bounding box 82 void GetCentre(CVector3D& centre) const { 83 centre=(m_Data[0]+m_Data[1])*0.5f; 92 void GetCentre(CVector3D& centre) const 93 { 94 centre = (m_Data[0] + m_Data[1]) * 0.5f; 84 95 } 85 96 86 97 /** … … public: 109 120 void Render() const; 110 121 111 122 private: 123 // Holds the minimal and maximal coordinate points in m_Data[0] and m_Data[1], respectively. 112 124 CVector3D m_Data[2]; 125 126 public: 127 static const CBound EMPTY; 128 113 129 }; 114 130 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 115 131 -
new file source/maths/Box.cpp
diff --git a/source/maths/Box.cpp b/source/maths/Box.cpp new file mode 100644 index 0000000..7b52cd8
- + 1 /* Copyright (C) 2011 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "Box.h" 21 22 #include <float.h> 23 24 const CBox CBox::EMPTY = CBox(); 25 26 bool CBox::RayIntersect(const CVector3D& origin, const CVector3D& dir, float& tMin_out, float& tMax_out) 27 { 28 // See Real-Time Rendering, Third Edition, p. 743 29 float tMin = -FLT_MAX; 30 float tMax = FLT_MAX; 31 32 CVector3D p = m_Center - origin; 33 34 for (int i = 0; i < 3; ++i) 35 { 36 float e = m_Basis[i].Dot(p); 37 float f = m_Basis[i].Dot(dir); 38 39 if(fabs(f) > 1e-10f) 40 { 41 float invF = 1.f/f; 42 float t1 = (e + m_HalfSizes[i]) * invF; 43 float t2 = (e - m_HalfSizes[i]) * invF; 44 45 if (t1 > t2) 46 { 47 float tmp = t1; 48 t1 = t2; 49 t2 = tmp; 50 } 51 if (t1 > tMin) tMin = t1; 52 if (t2 < tMax) tMax = t2; 53 if (tMin > tMax) return false; 54 if (tMax < 0) return false; 55 } 56 else 57 { 58 if(-e - m_HalfSizes[i] > 0 || -e + m_HalfSizes[i] < 0) return false; 59 } 60 } 61 62 tMin_out = tMin; 63 tMax_out = tMax; 64 return true; 65 } 66 No newline at end of file -
new file source/maths/Box.h
diff --git a/source/maths/Box.h b/source/maths/Box.h new file mode 100644 index 0000000..19cb0af
- + 1 /* Copyright (C) 2011 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 19 #ifndef INCLUDED_BOX 20 #define INCLUDED_BOX 21 22 #include "maths/Vector3D.h" 23 #include "maths/Bound.h" 24 25 /* 26 * Generic oriented box. Originally intended to be used an Oriented Bounding Box (OBB), as opposed to CBound which is an axis-aligned 27 * bounding box (AABB). 28 */ 29 class CBox 30 { 31 public: 32 33 /** 34 * Constructs a new oriented box centered at @p centered and with normalized side vectors @p u, @p v and @p w. These vectors should 35 * be mutually orthonormal for a proper rectangular box. The half-widths of the box in each direction are given by @p hU, @p hV 36 * and @p hW, respectively. 37 */ 38 CBox(const CVector3D& center, const CVector3D& u, const CVector3D& v, const CVector3D& w, const CVector3D& halfSizes) 39 : m_Center(center), m_HalfSizes(halfSizes) 40 { 41 m_Basis[0] = u; 42 m_Basis[1] = v; 43 m_Basis[2] = w; 44 } 45 46 /** 47 * Constructs a new oriented box from an axis-aligned bounding box (AABB). 48 */ 49 CBox(const CBound& bound) 50 { 51 if (bound.IsEmpty()) 52 { 53 SetEmpty(); 54 } 55 else 56 { 57 bound.GetCentre(m_Center); 58 59 // the axes of an AABB are the world-space axes 60 m_Basis[0].X = 1.f; m_Basis[0].Y = 0.f; m_Basis[0].Z = 0.f; 61 m_Basis[1].X = 0.f; m_Basis[1].Y = 1.f; m_Basis[1].Z = 0.f; 62 m_Basis[2].X = 0.f; m_Basis[2].Y = 0.f; m_Basis[2].Z = 1.f; 63 64 // element-wise division by two to get half sizes (remember, [1] and [0] are the max and min coord points) 65 m_HalfSizes = (bound[1] - bound[0]) * 0.5f; 66 } 67 } 68 69 /** 70 * Empty constructor 71 */ 72 CBox() 73 { 74 SetEmpty(); 75 } 76 77 /** 78 * Returns true if the ray originating in @p origin and with unit direction vector @p dir intersects this box, false otherwise. 79 * Additionally, returns the positive distances from the origin of the ray to the entry and exit points in the box in 80 * @p tmin and @p tmax. See also Real-Time Rendering, Third Edition by T. Akenine-Möller, p. 741--742. 81 * Should not be used if IsEmpty() is true. 82 * 83 * @param origin Origin of the ray. 84 * @param dir Direction vector of the ray. Must be of unit length. 85 */ 86 bool RayIntersect(const CVector3D& origin, const CVector3D& dir, float& tMin, float& tMax); 87 88 /** 89 * Returns the corner at coordinate (@p u, @p v, @p w). Each of @p u, @p v and @p w must be exactly 1 or -1. 90 * Should not be used if IsEmpty() is true. 91 */ 92 void GetCorner(int u, int v, int w, CVector3D& out) 93 { 94 out = m_Center + m_Basis[0]*(u*m_HalfSizes[0]) + m_Basis[1]*(v*m_HalfSizes[1]) + m_Basis[2]*(w*m_HalfSizes[2]); 95 } 96 97 void SetEmpty() 98 { 99 // everything is zero 100 m_Center = CVector3D(); 101 m_Basis[0] = CVector3D(); 102 m_Basis[1] = CVector3D(); 103 m_Basis[2] = CVector3D(); 104 m_HalfSizes = CVector3D(); 105 } 106 107 bool IsEmpty() 108 { 109 return ( m_Center.X == 0 && m_Center.Y == 0 && m_Center.Z == 0 && 110 m_Basis[0].X == 0 && m_Basis[0].Y == 0 && m_Basis[0].Z == 0 && 111 m_Basis[1].X == 0 && m_Basis[1].Y == 0 && m_Basis[1].Z == 0 && 112 m_Basis[2].X == 0 && m_Basis[2].Y == 0 && m_Basis[2].Z == 0 && 113 m_HalfSizes.X == 0 && m_HalfSizes.Y == 0 && m_HalfSizes.Z == 0); 114 } 115 116 public: 117 CVector3D m_Center; 118 CVector3D m_HalfSizes; 119 CVector3D m_Basis[3]; // orthonormal basis vectors (u,v,w) 120 121 static const CBox EMPTY; 122 }; 123 124 #endif INCLUDED_BOX 125 No newline at end of file -
source/maths/Matrix3D.h
diff --git a/source/maths/Matrix3D.h b/source/maths/Matrix3D.h index 0a14bd3..d42141f 100644
a b class CMatrix3D 35 35 public: 36 36 // the matrix data itself - accessible as either longhand names 37 37 // or via a flat or 2d array 38 // NOTE: _xy means row x, column y, so don't be fooled by the way they're listed below 38 39 union { 39 40 struct { 40 41 float _11, _21, _31, _41; -
source/renderer/Renderer.cpp
diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp index b8308bc..6215063 100644
a b public: 1041 1041 1042 1042 bool Filter(CModel *model) 1043 1043 { 1044 return m_Frustum.IsBoxVisible(CVector3D(0, 0, 0), model->Get BoundsRec());1044 return m_Frustum.IsBoxVisible(CVector3D(0, 0, 0), model->GetWorldBoundsRec()); 1045 1045 } 1046 1046 1047 1047 private: … … void CRenderer::SubmitNonRecursive(CModel* model) 1753 1753 { 1754 1754 if (model->GetFlags() & MODELFLAG_CASTSHADOWS) { 1755 1755 // PROFILE( "updating shadow bounds" ); 1756 m->shadow->AddShadowedBound(model->Get Bounds());1756 m->shadow->AddShadowedBound(model->GetWorldBounds()); 1757 1757 } 1758 1758 1759 1759 // Tricky: The call to GetBounds() above can invalidate the position -
source/renderer/TerrainRenderer.cpp
diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp index 13b71bc..56b1eca 100644
a b bool TerrainRenderer::CullPatches(const CFrustum* frustum) 173 173 m->filteredPatches.clear(); 174 174 for (std::vector<CPatchRData*>::iterator it = m->visiblePatches.begin(); it != m->visiblePatches.end(); it++) 175 175 { 176 if (frustum->IsBoxVisible(CVector3D(0, 0, 0), (*it)->GetPatch()->Get Bounds()))176 if (frustum->IsBoxVisible(CVector3D(0, 0, 0), (*it)->GetPatch()->GetWorldBounds())) 177 177 m->filteredPatches.push_back(*it); 178 178 } 179 179 180 180 m->filteredDecals.clear(); 181 181 for (std::vector<CDecalRData*>::iterator it = m->visibleDecals.begin(); it != m->visibleDecals.end(); it++) 182 182 { 183 if (frustum->IsBoxVisible(CVector3D(0, 0, 0), (*it)->GetDecal()->Get Bounds()))183 if (frustum->IsBoxVisible(CVector3D(0, 0, 0), (*it)->GetDecal()->GetWorldBounds())) 184 184 m->filteredDecals.push_back(*it); 185 185 } 186 186 -
source/simulation2/components/CCmpProjectileManager.cpp
diff --git a/source/simulation2/components/CCmpProjectileManager.cpp b/source/simulation2/components/CCmpProjectileManager.cpp index e0ac1cc..c7ffccd 100644
a b void CCmpProjectileManager::RenderSubmit(SceneCollector& collector, const CFrust 347 347 348 348 model.ValidatePosition(); 349 349 350 if (culling && !frustum.IsBoxVisible(CVector3D(0, 0, 0), model.Get Bounds()))350 if (culling && !frustum.IsBoxVisible(CVector3D(0, 0, 0), model.GetWorldBounds())) 351 351 continue; 352 352 353 353 // TODO: do something about LOS (copy from CCmpVisualActor) -
source/simulation2/components/CCmpSelectable.cpp
diff --git a/source/simulation2/components/CCmpSelectable.cpp b/source/simulation2/components/CCmpSelectable.cpp index e9aa3d2..651cb3f 100644
a b 22 22 23 23 #include "ICmpPosition.h" 24 24 #include "ICmpFootprint.h" 25 #include "ICmpVisual.h" 25 26 #include "simulation2/MessageTypes.h" 26 27 #include "simulation2/helpers/Render.h" 27 28 … … public: 153 154 void RenderSubmit(SceneCollector& collector) 154 155 { 155 156 // (This is only called if a > 0) 156 157 157 collector.Submit(&m_Overlay); 158 159 if (ICmpSelectable::s_EnableDebugOverlays) 160 { 161 static SOverlayLine* boundOverlayLine = new SOverlayLine; 162 static SOverlayLine* selectionOverlayLine = new SOverlayLine; 163 164 CmpPtr<ICmpVisual> cmpVisual(GetSimContext(), GetEntityId()); 165 if (!cmpVisual.null()) 166 { 167 CBound bound = cmpVisual->GetBounds(); 168 CVector3D tmin = bound[0]; 169 CVector3D tmax = bound[1]; 170 171 boundOverlayLine->m_Thickness = 2; 172 boundOverlayLine->m_Color = CColor(1.f, 0.f, 0.f, 1.f); 173 boundOverlayLine->m_Coords.clear(); 174 // floor square 175 boundOverlayLine->m_Coords.push_back(tmin.X); boundOverlayLine->m_Coords.push_back(tmin.Y); boundOverlayLine->m_Coords.push_back(tmin.Z); 176 boundOverlayLine->m_Coords.push_back(tmax.X); boundOverlayLine->m_Coords.push_back(tmin.Y); boundOverlayLine->m_Coords.push_back(tmin.Z); 177 boundOverlayLine->m_Coords.push_back(tmax.X); boundOverlayLine->m_Coords.push_back(tmin.Y); boundOverlayLine->m_Coords.push_back(tmax.Z); 178 boundOverlayLine->m_Coords.push_back(tmin.X); boundOverlayLine->m_Coords.push_back(tmin.Y); boundOverlayLine->m_Coords.push_back(tmax.Z); 179 boundOverlayLine->m_Coords.push_back(tmin.X); boundOverlayLine->m_Coords.push_back(tmin.Y); boundOverlayLine->m_Coords.push_back(tmin.Z); 180 // roof square 181 boundOverlayLine->m_Coords.push_back(tmin.X); boundOverlayLine->m_Coords.push_back(tmax.Y); boundOverlayLine->m_Coords.push_back(tmin.Z); 182 boundOverlayLine->m_Coords.push_back(tmax.X); boundOverlayLine->m_Coords.push_back(tmax.Y); boundOverlayLine->m_Coords.push_back(tmin.Z); 183 boundOverlayLine->m_Coords.push_back(tmax.X); boundOverlayLine->m_Coords.push_back(tmax.Y); boundOverlayLine->m_Coords.push_back(tmax.Z); 184 boundOverlayLine->m_Coords.push_back(tmin.X); boundOverlayLine->m_Coords.push_back(tmax.Y); boundOverlayLine->m_Coords.push_back(tmax.Z); 185 boundOverlayLine->m_Coords.push_back(tmin.X); boundOverlayLine->m_Coords.push_back(tmax.Y); boundOverlayLine->m_Coords.push_back(tmin.Z); 186 // supports 187 collector.Submit(boundOverlayLine); 188 189 // ------------------------------------------- 190 191 CBox orientedBox = cmpVisual->GetSelectionBox(); 192 selectionOverlayLine->m_Thickness = 2; 193 selectionOverlayLine->m_Color = CColor(0.f, 1.f, 0.f, 1.f); 194 selectionOverlayLine->m_Coords.clear(); 195 196 CVector3D corners[8]; 197 orientedBox.GetCorner(-1, -1, -1, corners[0]); 198 orientedBox.GetCorner( 1, -1, -1, corners[1]); 199 orientedBox.GetCorner( 1, -1, 1, corners[2]); 200 orientedBox.GetCorner(-1, -1, 1, corners[3]); 201 orientedBox.GetCorner(-1, 1, -1, corners[4]); 202 orientedBox.GetCorner( 1, 1, -1, corners[5]); 203 orientedBox.GetCorner( 1, 1, 1, corners[6]); 204 orientedBox.GetCorner(-1, 1, 1, corners[7]); 205 206 selectionOverlayLine->m_Coords.push_back(corners[0].X); selectionOverlayLine->m_Coords.push_back(corners[0].Y); selectionOverlayLine->m_Coords.push_back(corners[0].Z); 207 selectionOverlayLine->m_Coords.push_back(corners[1].X); selectionOverlayLine->m_Coords.push_back(corners[1].Y); selectionOverlayLine->m_Coords.push_back(corners[1].Z); 208 selectionOverlayLine->m_Coords.push_back(corners[2].X); selectionOverlayLine->m_Coords.push_back(corners[2].Y); selectionOverlayLine->m_Coords.push_back(corners[2].Z); 209 selectionOverlayLine->m_Coords.push_back(corners[3].X); selectionOverlayLine->m_Coords.push_back(corners[3].Y); selectionOverlayLine->m_Coords.push_back(corners[3].Z); 210 selectionOverlayLine->m_Coords.push_back(corners[0].X); selectionOverlayLine->m_Coords.push_back(corners[0].Y); selectionOverlayLine->m_Coords.push_back(corners[0].Z); 211 212 selectionOverlayLine->m_Coords.push_back(corners[4].X); selectionOverlayLine->m_Coords.push_back(corners[4].Y); selectionOverlayLine->m_Coords.push_back(corners[4].Z); 213 selectionOverlayLine->m_Coords.push_back(corners[5].X); selectionOverlayLine->m_Coords.push_back(corners[5].Y); selectionOverlayLine->m_Coords.push_back(corners[5].Z); 214 selectionOverlayLine->m_Coords.push_back(corners[6].X); selectionOverlayLine->m_Coords.push_back(corners[6].Y); selectionOverlayLine->m_Coords.push_back(corners[6].Z); 215 selectionOverlayLine->m_Coords.push_back(corners[7].X); selectionOverlayLine->m_Coords.push_back(corners[7].Y); selectionOverlayLine->m_Coords.push_back(corners[7].Z); 216 selectionOverlayLine->m_Coords.push_back(corners[4].X); selectionOverlayLine->m_Coords.push_back(corners[4].Y); selectionOverlayLine->m_Coords.push_back(corners[4].Z); 217 218 collector.Submit(selectionOverlayLine); 219 } 220 } 158 221 } 159 222 }; 160 223 -
source/simulation2/components/CCmpVisualActor.cpp
diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp index f35cb80..ce29a98 100644
a b public: 224 224 { 225 225 if (!m_Unit) 226 226 return CBound(); 227 return m_Unit->GetModel().GetBounds(); 227 // TODO: this should probably be GetWorldBoundsRec(), so that it also includes any props 228 return m_Unit->GetModel().GetWorldBounds(); 229 } 230 231 virtual CBox GetSelectionBox() 232 { 233 if (!m_Unit) 234 return CBox(); 235 return m_Unit->GetModel().GetSelectionBox(); 228 236 } 229 237 230 238 virtual CVector3D GetPosition() … … void CCmpVisualActor::RenderSubmit(SceneCollector& collector, const CFrustum& fr 482 490 483 491 CModelAbstract& model = m_Unit->GetModel(); 484 492 485 if (culling && !frustum.IsBoxVisible(CVector3D(0, 0, 0), model.Get BoundsRec()))493 if (culling && !frustum.IsBoxVisible(CVector3D(0, 0, 0), model.GetWorldBoundsRec())) 486 494 return; 487 495 488 496 collector.SubmitRecursive(&model); -
source/simulation2/components/ICmpSelectable.cpp
diff --git a/source/simulation2/components/ICmpSelectable.cpp b/source/simulation2/components/ICmpSelectable.cpp index 20f0b09..1f92268 100644
a b 26 26 BEGIN_INTERFACE_WRAPPER(Selectable) 27 27 DEFINE_INTERFACE_METHOD_1("SetSelectionHighlight", void, ICmpSelectable, SetSelectionHighlight, CColor) 28 28 END_INTERFACE_WRAPPER(Selectable) 29 30 bool ICmpSelectable::s_EnableDebugOverlays = false; 31 No newline at end of file -
source/simulation2/components/ICmpSelectable.h
diff --git a/source/simulation2/components/ICmpSelectable.h b/source/simulation2/components/ICmpSelectable.h index eadd554..484b455 100644
a b public: 32 32 virtual void SetSelectionHighlight(CColor color) = 0; 33 33 34 34 DECLARE_INTERFACE_TYPE(Selectable) 35 36 static bool s_EnableDebugOverlays; 35 37 }; 36 38 37 39 #endif // INCLUDED_ICMPSELECTABLE -
source/simulation2/components/ICmpVisual.h
diff --git a/source/simulation2/components/ICmpVisual.h b/source/simulation2/components/ICmpVisual.h index 68f1108..4d7a12a 100644
a b 20 20 21 21 #include "simulation2/system/Interface.h" 22 22 23 #include "maths/Box.h" 23 24 #include "maths/Bound.h" 24 25 #include "maths/Fixed.h" 25 26 #include "lib/file/vfs/vfs_path.h" … … public: 37 38 virtual CBound GetBounds() = 0; 38 39 39 40 /** 41 * Get the oriented world-space bounding box of the object's visual representation, clipped at the Y=0 plane in object space 42 * to prevent it from extending into the terrain. The primary difference with GetBounds is that this bounding box is not aligned 43 * to the world axes, but arbitrarily rotated according to the model transform. 44 */ 45 virtual CBox GetSelectionBox() = 0; 46 47 /** 40 48 * Get the world-space position of the base point of the object's visual representation. 41 49 * (Not safe for use in simulation code.) 42 50 */ -
source/simulation2/helpers/Selection.cpp
diff --git a/source/simulation2/helpers/Selection.cpp b/source/simulation2/helpers/Selection.cpp index 0405894..9b61744 100644
a b std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simu 51 51 if (cmpVisual.null()) 52 52 continue; 53 53 54 CBound bounds = cmpVisual->GetBounds(); 54 //CBound bounds = cmpVisual->GetBounds(); 55 CBox selectionBox = cmpVisual->GetSelectionBox(); 56 if (selectionBox.IsEmpty()) 57 continue; 55 58 56 59 float tmin, tmax; 57 if (! bounds.RayIntersect(origin, dir, tmin, tmax))60 if (!selectionBox.RayIntersect(origin, dir, tmin, tmax)) 58 61 continue; 59 62 60 63 // Find the perpendicular distance from the object's centre to the picker ray 61 64 62 CVector3D centre; 63 bounds.GetCentre(centre); 64 65 CVector3D closest = origin + dir * (centre - origin).Dot(dir); 66 float dist2 = (closest - centre).LengthSquared(); 65 CVector3D closest = origin + dir * (selectionBox.m_Center - origin).Dot(dir); 66 float dist2 = (closest - selectionBox.m_Center).LengthSquared(); 67 67 68 68 hits.push_back(std::make_pair(dist2, ent)); 69 69 }