You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/CryCommon/QTangent.h

158 lines
5.0 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_CRYCOMMON_QTANGENT_H
#define CRYINCLUDE_CRYCOMMON_QTANGENT_H
#pragma once
namespace QTangent {
// Computes a QTangent from a frame and reflection scalar representing the
// tangent space.
// Will also ensure the resulting QTangent is suitable for 16bit quantization.
ILINE Quat FromFrameReflection(Quat frame, const float reflection)
{
frame.v = -frame.v;
if (frame.w < 0.0f)
{
frame = -frame;
}
// Make sure w is never 0 by applying the smallest possible bias.
// This is needed in order to have sign() never return 0 in the shaders.
static const float BIAS_16BIT = 1.0f / 32767.0f;
static const float BIAS_SCALE_16BIT = sqrtf(1.0f - BIAS_16BIT * BIAS_16BIT);
if (frame.w < BIAS_16BIT && frame.w > -BIAS_16BIT)
{
frame *= BIAS_SCALE_16BIT;
frame.w = BIAS_16BIT;
}
if (reflection < 0.0f)
{
frame = -frame;
}
return frame;
}
ILINE Quat FromFrameReflection(const Matrix33& frame, const float reflection)
{
Quat quat(frame);
quat.Normalize();
return FromFrameReflection(quat, reflection);
}
ILINE Quat FromFrameReflection16Safe(Matrix33 frame, const float reflection)
{
frame.OrthonormalizeFast();
if (!frame.IsOrthonormalRH(0.1f))
{
frame.SetIdentity();
}
return FromFrameReflection(frame, reflection);
}
ILINE void ToTangentBitangentReflection(const Quat& qtangent, Vec3& tangent, Vec3& bitangent, float& reflection)
{
tangent = qtangent.GetColumn0();
bitangent = qtangent.GetColumn1();
reflection = qtangent.w < 0.0f ? -1.0f : +1.0f;
}
} // namespace QTangent
// Auxiliary helper functions
#include <IIndexedMesh.h> // <> required for Interfuscator
ILINE Quat MeshTangentFrameToQTangent(const SMeshTangents& tangents)
{
SMeshTangents tb = tangents;
Vec3 tangent32, bitangent32;
int16 reflection;
tb.GetTB(tangent32, bitangent32);
tb.GetR(reflection);
Matrix33 frame;
frame.SetRow(0, tangent32);
frame.SetRow(1, bitangent32);
frame.SetRow(2, tangent32.Cross(bitangent32).GetNormalized());
return QTangent::FromFrameReflection16Safe(frame, reflection);
}
ILINE Quat MeshTangentFrameToQTangent(const Vec4sf& tangent, const Vec4sf& bitangent)
{
return MeshTangentFrameToQTangent(SMeshTangents(tangent, bitangent));
}
ILINE Quat MeshTangentFrameToQTangent(const SPipTangents& tangents)
{
return MeshTangentFrameToQTangent(SMeshTangents(tangents));
}
ILINE bool MeshTangentsFrameToQTangents(
const Vec4sf* pTangent, const uint tangentStride,
const Vec4sf* pBitangent, const uint bitangentStride, const uint count,
SPipQTangents* pQTangents, const uint qtangentStride)
{
Quat qtangent;
for (uint i = 0; i < count; ++i)
{
qtangent = MeshTangentFrameToQTangent(*pTangent, *pBitangent);
SMeshQTangents(qtangent).ExportTo(*pQTangents);
pTangent = (const Vec4sf*)(((const uint8*)pTangent) + tangentStride);
pBitangent = (const Vec4sf*)(((const uint8*)pBitangent) + bitangentStride);
pQTangents = (SPipQTangents*)(((uint8*)pQTangents) + qtangentStride);
}
return true;
}
ILINE bool MeshTangentsFrameToQTangents(
const SPipTangents* pTangents, const uint tangentStride, const uint count,
SPipQTangents* pQTangents, const uint qtangentStride)
{
Quat qtangent;
for (uint i = 0; i < count; ++i)
{
qtangent = MeshTangentFrameToQTangent(*pTangents);
SMeshQTangents(qtangent).ExportTo(*pQTangents);
pTangents = (const SPipTangents*)(((const uint8*)pTangents) + tangentStride);
pQTangents = (SPipQTangents*)(((uint8*)pQTangents) + qtangentStride);
}
return true;
}
ILINE bool MeshTangentsFrameToQTangents(
const SMeshTangents* pTangents, const uint tangentStride, const uint count,
SMeshQTangents* pQTangents, const uint qtangentStride)
{
Quat qtangent;
for (uint i = 0; i < count; ++i)
{
qtangent = MeshTangentFrameToQTangent(*pTangents);
*pQTangents = SMeshQTangents(qtangent);
pTangents = (const SMeshTangents*)(((const uint8*)pTangents) + tangentStride);
pQTangents = (SMeshQTangents*)(((uint8*)pQTangents) + qtangentStride);
}
return true;
}
#endif // CRYINCLUDE_CRYCOMMON_QTANGENT_H