Line data Source code
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 : #include "ps/CLogger.h"
23 :
24 0 : const CBoundingBoxOriented& CModelAbstract::GetSelectionBox()
25 : {
26 0 : if (!m_SelectionBoxValid)
27 : {
28 0 : CalcSelectionBox();
29 0 : m_SelectionBoxValid = true;
30 : }
31 0 : return m_SelectionBox;
32 : }
33 :
34 0 : void CModelAbstract::CalcSelectionBox()
35 : {
36 0 : if (m_CustomSelectionShape)
37 : {
38 : // custom shape
39 0 : switch(m_CustomSelectionShape->m_Type)
40 : {
41 0 : case CustomSelectionShape::BOX:
42 : {
43 : // create object-space bounds according to the information in the descriptor, and transform them to world-space.
44 : // the box is centered on the X and Z axes, but extends from 0 to its height on the Y axis.
45 0 : const float width = m_CustomSelectionShape->m_Size0;
46 0 : const float depth = m_CustomSelectionShape->m_Size1;
47 0 : const float height = m_CustomSelectionShape->m_Height;
48 :
49 0 : CBoundingBoxAligned bounds;
50 0 : bounds += CVector3D(-width/2.f, 0, -depth/2.f);
51 0 : bounds += CVector3D( width/2.f, height, depth/2.f);
52 :
53 0 : bounds.Transform(GetTransform(), m_SelectionBox);
54 : }
55 0 : break;
56 0 : case CustomSelectionShape::CYLINDER:
57 : {
58 : // TODO: unimplemented
59 0 : m_SelectionBox.SetEmpty();
60 0 : LOGWARNING("[ModelAbstract] TODO: Cylinder selection boxes are not yet implemented. Use BOX or BOUNDS selection shapes instead.");
61 : }
62 0 : break;
63 0 : default:
64 : {
65 0 : m_SelectionBox.SetEmpty();
66 : //LOGWARNING("[ModelAbstract] Unrecognized selection shape type: %ld", m_CustomSelectionShape->m_Type);
67 0 : debug_warn("[ModelAbstract] Unrecognized selection shape type");
68 : }
69 0 : break;
70 : }
71 : }
72 : else
73 : {
74 : // standard method
75 :
76 : // Get the object-space bounds that should be used to construct this model (and its children)'s selection box
77 0 : CBoundingBoxAligned objBounds = GetObjectSelectionBoundsRec();
78 0 : if (objBounds.IsEmpty())
79 : {
80 0 : m_SelectionBox.SetEmpty(); // model does not wish to participate in selection
81 0 : return;
82 : }
83 :
84 : // Prevent the bounding box from extending through the terrain; clip the lower plane at Y=0 in object space.
85 0 : if (objBounds[1].Y > 0.f) // should always be the case, unless the models are defined really weirdly
86 0 : objBounds[0].Y = std::max(0.f, objBounds[0].Y);
87 :
88 : // transform object-space axis-aligned bounds to world-space arbitrary-aligned box
89 0 : objBounds.Transform(GetTransform(), m_SelectionBox);
90 : }
91 :
92 3 : }
|