Files
o3de/Gems/SurfaceData/Code/Source/SurfaceDataUtility.cpp
T
Mike Balfour 567156b85a [ATOM-4343] Temporary fix for vegetation raycasts until full solution is implemented. (#1572)
Currently, the first time a raycast is attempted for a model, the raycast will fail and the model's kdtree will asynchronously get built.  This breaks the vegetation system, which expects the queries to always work.  This adds in a brute-force fallback for use while the kdtree is building.  However, other use cases like the Editor mouse cursor selection raycast still should get the current "silent failure" behavior, because otherwise the Editor will lock up for several seconds the first time the mouse moves over an extremely complex model.
2021-06-24 17:30:24 -05:00

44 lines
1.7 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "SurfaceData_precompiled.h"
#include <SurfaceData/Utility/SurfaceDataUtility.h>
#include <Atom/RPI.Reflect/Model/ModelAssetCreator.h>
namespace SurfaceData
{
bool GetMeshRayIntersection(
const AZ::RPI::ModelAsset& meshAsset, const AZ::Transform& meshTransform,
const AZ::Transform& meshTransformInverse, const AZ::Vector3& nonUniformScale,
const AZ::Vector3& rayStart, const AZ::Vector3& rayEnd,
AZ::Vector3& outPosition, AZ::Vector3& outNormal)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Entity);
const AZ::Vector3 clampedScale = nonUniformScale.GetMax(AZ::Vector3(AZ::MinTransformScale));
// Transform everything into model space
const AZ::Vector3 rayStartLocal = meshTransformInverse.TransformPoint(rayStart) / clampedScale;
const AZ::Vector3 rayEndLocal = meshTransformInverse.TransformPoint(rayEnd) / clampedScale;
const AZ::Vector3 rayDirectionLocal = (rayEndLocal - rayStartLocal).GetNormalized();
float distance = rayEndLocal.GetDistance(rayStartLocal);
AZ::Vector3 normalLocal;
constexpr bool AllowBruteForce = true;
if (meshAsset.LocalRayIntersectionAgainstModel(rayStartLocal, rayDirectionLocal, AllowBruteForce, distance, normalLocal))
{
// Transform everything back to world space
outPosition = meshTransform.TransformPoint((rayStartLocal + (rayDirectionLocal * distance)) * clampedScale);
outNormal = meshTransform.TransformVector(normalLocal * clampedScale);
return true;
}
return false;
}
}