| 173 | } |
| 174 | |
| 175 | void Picker::ExecuteRecursive(std::shared_ptr<Spatial> const& object) |
| 176 | { |
| 177 | auto visual = std::dynamic_pointer_cast<Visual>(object); |
| 178 | if (visual) |
| 179 | { |
| 180 | if (visual->worldBound.TestIntersection(HProject(mOrigin), HProject(mDirection), mTMin, mTMax)) |
| 181 | { |
| 182 | // Convert the linear component to model-space coordinates. |
| 183 | Matrix4x4<float> const& invWorldMatrix = visual->worldTransform.GetHInverse(); |
| 184 | Line3<float> line; |
| 185 | Vector4<float> temp; |
| 186 | #if defined (GTE_USE_VEC_MAT) |
| 187 | temp = mOrigin * invWorldMatrix; |
| 188 | line.origin = { temp[0], temp[1], temp[2] }; |
| 189 | temp = mDirection * invWorldMatrix; |
| 190 | line.direction = { temp[0], temp[1], temp[2] }; |
| 191 | #else |
| 192 | temp = invWorldMatrix * mOrigin; |
| 193 | line.origin = { temp[0], temp[1], temp[2] }; |
| 194 | temp = invWorldMatrix * mDirection; |
| 195 | line.direction = { temp[0], temp[1], temp[2] }; |
| 196 | #endif |
| 197 | // The world transformation might have non-unit scales, in which case the |
| 198 | // model-space line direction is not unit length. |
| 199 | Normalize(line.direction); |
| 200 | |
| 201 | // Get the position data. |
| 202 | VertexBuffer* vbuffer = visual->GetVertexBuffer().get(); |
| 203 | std::set<uint32_t> required; |
| 204 | required.insert(DF_R32G32B32_FLOAT); |
| 205 | required.insert(DF_R32G32B32A32_FLOAT); |
| 206 | char const* positions = vbuffer->GetChannel(VASemantic::POSITION, 0, required); |
| 207 | LogAssert(positions != nullptr, "Expecting 3D positions."); |
| 208 | |
| 209 | // The picking algorithm depends on the primitive type. |
| 210 | uint32_t vstride = vbuffer->GetElementSize(); |
| 211 | IndexBuffer* ibuffer = visual->GetIndexBuffer().get(); |
| 212 | uint32_t primitiveType = ibuffer->GetPrimitiveType(); |
| 213 | if (primitiveType & IP_HAS_TRIANGLES) |
| 214 | { |
| 215 | PickTriangles(visual, positions, vstride, ibuffer, line); |
| 216 | } |
| 217 | else if (primitiveType & IP_HAS_SEGMENTS) |
| 218 | { |
| 219 | PickSegments(visual, positions, vstride, ibuffer, line); |
| 220 | } |
| 221 | else if (primitiveType & IP_HAS_POINTS) |
| 222 | { |
| 223 | PickPoints(visual, positions, vstride, ibuffer, line); |
| 224 | } |
| 225 | } |
| 226 | return; |
| 227 | } |
| 228 | |
| 229 | auto node = std::dynamic_pointer_cast<Node>(object); |
| 230 | if (node) |
| 231 | { |
| 232 | if (node->worldBound.TestIntersection(HProject(mOrigin), HProject(mDirection), mTMin, mTMax)) |
nothing calls this directly
no test coverage detected