OSDN Git Service

DTXMania089リリースに際してのtag付け。
[dtxmania/dtxmania.git] / 110401(DTXMania089) / SlimDXc_Jun2010(VC++2008) / source / math / Ray.cpp
1 #include "stdafx.h"\r
2 /*\r
3 * Copyright (c) 2007-2010 SlimDX Group\r
4\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
6 * of this software and associated documentation files (the "Software"), to deal\r
7 * in the Software without restriction, including without limitation the rights\r
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
9 * copies of the Software, and to permit persons to whom the Software is\r
10 * furnished to do so, subject to the following conditions:\r
11\r
12 * The above copyright notice and this permission notice shall be included in\r
13 * all copies or substantial portions of the Software.\r
14\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
21 * THE SOFTWARE.\r
22 */\r
23 \r
24 #include <d3dx9.h>\r
25 \r
26 #include "BoundingBox.h"\r
27 #include "BoundingSphere.h"\r
28 #include "Plane.h"\r
29 #include "Ray.h"\r
30 \r
31 using namespace System;\r
32 using namespace System::Globalization;\r
33 \r
34 namespace SlimDX\r
35 {\r
36         Ray::Ray( Vector3 position, Vector3 direction )\r
37         {\r
38                 Position = position;\r
39                 Direction = direction;\r
40         }\r
41 \r
42         bool Ray::Intersects( Ray ray, Plane plane, [Out] float% distance )\r
43         {\r
44                 ray.Direction.Normalize();\r
45                 float dotDirection = (plane.Normal.X * ray.Direction.X) + (plane.Normal.Y * ray.Direction.Y) + (plane.Normal.Z * ray.Direction.Z);\r
46 \r
47                 if( Math::Abs( dotDirection ) < 0.000001f )\r
48                 {\r
49                         distance = 0;\r
50                         return false;\r
51                 }\r
52 \r
53                 float dotPosition = (plane.Normal.X * ray.Position.X) + (plane.Normal.Y * ray.Position.Y) + (plane.Normal.Z * ray.Position.Z);\r
54                 float num = ( -plane.D - dotPosition ) / dotDirection;\r
55 \r
56                 if( num < 0.0f )\r
57                 {\r
58                         if( num < -0.000001f )\r
59                         {\r
60                                 distance = 0;\r
61                                 return false;\r
62                         }\r
63                         num = 0.0f;\r
64                 }\r
65 \r
66                 distance = num;\r
67                 return true;\r
68         }\r
69 \r
70         bool Ray::Intersects( Ray ray, Vector3 vertex1, Vector3 vertex2, Vector3 vertex3, [Out] float% distance )\r
71         {\r
72                 FLOAT u, v;\r
73                 pin_ptr<float> pinnedDist = &distance;\r
74 \r
75                 if( D3DXIntersectTri( reinterpret_cast<D3DXVECTOR3*>( &vertex1 ), \r
76                         reinterpret_cast<D3DXVECTOR3*>( &vertex2 ), reinterpret_cast<D3DXVECTOR3*>( &vertex3 ),\r
77                         reinterpret_cast<D3DXVECTOR3*>( &ray.Position ), reinterpret_cast<D3DXVECTOR3*>( &ray.Direction ),\r
78                         &u, &v, reinterpret_cast<FLOAT*>( pinnedDist ) ) )\r
79                         return true;\r
80                 else\r
81                         return false;\r
82         }\r
83 \r
84         bool Ray::Intersects( Ray ray, BoundingBox box, [Out] float% distance )\r
85         {\r
86                 float d = 0.0f;\r
87                 float maxValue = float::MaxValue;\r
88 \r
89                 ray.Direction.Normalize();\r
90                 if( Math::Abs( ray.Direction.X ) < 0.0000001 )\r
91                 {\r
92                         if( ray.Position.X < box.Minimum.X || ray.Position.X > box.Maximum.X )\r
93                         {\r
94                                 distance = 0.0f;\r
95                                 return false;\r
96                         }\r
97                 }\r
98                 else\r
99                 {\r
100                         float inv = 1.0f / ray.Direction.X;\r
101                         float min = (box.Minimum.X - ray.Position.X) * inv;\r
102                         float max = (box.Maximum.X - ray.Position.X) * inv;\r
103 \r
104                         if( min > max )\r
105                         {\r
106                                 float temp = min;\r
107                                 min = max;\r
108                                 max = temp;\r
109                         }\r
110 \r
111                         d = Math::Max( min, d );\r
112                         maxValue = Math::Min( max, maxValue );\r
113 \r
114                         if( d > maxValue )\r
115                         {\r
116                                 distance = 0.0f;\r
117                                 return false;\r
118                         }\r
119                 }\r
120 \r
121                 if( Math::Abs( ray.Direction.Y ) < 0.0000001 )\r
122                 {\r
123                         if( ray.Position.Y < box.Minimum.Y || ray.Position.Y > box.Maximum.Y )\r
124                         {\r
125                                 distance = 0.0f;\r
126                                 return false;\r
127                         }\r
128                 }\r
129                 else\r
130                 {\r
131                         float inv = 1.0f / ray.Direction.Y;\r
132                         float min = (box.Minimum.Y - ray.Position.Y) * inv;\r
133                         float max = (box.Maximum.Y - ray.Position.Y) * inv;\r
134 \r
135                         if( min > max )\r
136                         {\r
137                                 float temp = min;\r
138                                 min = max;\r
139                                 max = temp;\r
140                         }\r
141 \r
142                         d = Math::Max( min, d );\r
143                         maxValue = Math::Min( max, maxValue );\r
144 \r
145                         if( d > maxValue )\r
146                         {\r
147                                 distance = 0.0f;\r
148                                 return false;\r
149                         }\r
150                 }\r
151 \r
152                 if( Math::Abs( ray.Direction.Z ) < 0.0000001 )\r
153                 {\r
154                         if( ray.Position.Z < box.Minimum.Z || ray.Position.Z > box.Maximum.Z )\r
155                         {\r
156                                 distance = 0.0f;\r
157                                 return false;\r
158                         }\r
159                 }\r
160                 else\r
161                 {\r
162                         float inv = 1.0f / ray.Direction.Z;\r
163                         float min = (box.Minimum.Z - ray.Position.Z) * inv;\r
164                         float max = (box.Maximum.Z - ray.Position.Z) * inv;\r
165 \r
166                         if( min > max )\r
167                         {\r
168                                 float temp = min;\r
169                                 min = max;\r
170                                 max = temp;\r
171                         }\r
172 \r
173                         d = Math::Max( min, d );\r
174                         maxValue = Math::Min( max, maxValue );\r
175 \r
176                         if( d > maxValue )\r
177                         {\r
178                                 distance = 0.0f;\r
179                                 return false;\r
180                         }\r
181                 }\r
182 \r
183                 distance = d;\r
184                 return true;\r
185         }\r
186 \r
187         bool Ray::Intersects( Ray ray, BoundingSphere sphere, [Out] float% distance )\r
188         {\r
189                 float x = sphere.Center.X - ray.Position.X;\r
190                 float y = sphere.Center.Y - ray.Position.Y;\r
191                 float z = sphere.Center.Z - ray.Position.Z;\r
192                 float pyth = (x * x) + (y * y) + (z * z);\r
193                 float rr = sphere.Radius * sphere.Radius;\r
194 \r
195                 if( pyth <= rr )\r
196                 {\r
197                         distance = 0.0f;\r
198                         return true;\r
199                 }\r
200 \r
201                 ray.Direction.Normalize();\r
202                 float dot = (x * ray.Direction.X) + (y * ray.Direction.Y) + (z * ray.Direction.Z);\r
203                 if( dot < 0.0f )\r
204                 {\r
205                         distance = 0.0f;\r
206                         return false;\r
207                 }\r
208 \r
209                 float temp = pyth - (dot * dot);\r
210                 if( temp > rr )\r
211                 {\r
212                         distance = 0.0f;\r
213                         return false;\r
214                 }\r
215 \r
216                 distance = dot - static_cast<float>( Math::Sqrt( static_cast<double>( rr - temp ) ) );\r
217                 return true;\r
218         }\r
219 \r
220         bool Ray::operator == ( Ray left, Ray right )\r
221         {\r
222                 return Ray::Equals( left, right );\r
223         }\r
224 \r
225         bool Ray::operator != ( Ray left, Ray right )\r
226         {\r
227                 return !Ray::Equals( left, right );\r
228         }\r
229 \r
230         String^ Ray::ToString()\r
231         {\r
232                 return String::Format( CultureInfo::CurrentCulture, "Position:{0} Direction:{1}", Position.ToString(), Direction.ToString() );\r
233         }\r
234 \r
235         int Ray::GetHashCode()\r
236         {\r
237                 return Position.GetHashCode() + Direction.GetHashCode();\r
238         }\r
239 \r
240         bool Ray::Equals( Object^ value )\r
241         {\r
242                 if( value == nullptr )\r
243                         return false;\r
244 \r
245                 if( value->GetType() != GetType() )\r
246                         return false;\r
247 \r
248                 return Equals( safe_cast<Ray>( value ) );\r
249         }\r
250 \r
251         bool Ray::Equals( Ray value )\r
252         {\r
253                 return ( Position == value.Position && Direction == value.Direction );\r
254         }\r
255 \r
256         bool Ray::Equals( Ray% value1, Ray% value2 )\r
257         {\r
258                 return ( value1.Position == value2.Position && value1.Direction == value2.Direction );\r
259         }\r
260 }