mirror of
https://github.com/overte-org/overte.git
synced 2025-06-17 20:20:42 +02:00
Removed SKIN_COMP define, re-enabled cauterization
This commit is contained in:
parent
b69edceb4f
commit
e86fd4f992
10 changed files with 38 additions and 162 deletions
|
@ -1820,8 +1820,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
|
||||
if (_skeletonModel->isLoaded() && !_skeletonModel->getRig().getAnimNode()) {
|
||||
initHeadBones();
|
||||
// AJT HACK DISABLE CAUTERIZE
|
||||
//_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
||||
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
||||
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
||||
initAnimGraph();
|
||||
_isAnimatingScale = true;
|
||||
|
@ -1913,9 +1912,7 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) {
|
|||
// toggle using the cauterizedBones depending on where the camera is and the rendering pass type.
|
||||
const bool shouldDrawHead = shouldRenderHead(renderArgs);
|
||||
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||
// AJT: DISABLE CAUTER
|
||||
// _skeletonModel->setEnableCauterization(!shouldDrawHead);
|
||||
_skeletonModel->setEnableCauterization(false);
|
||||
_skeletonModel->setEnableCauterization(!shouldDrawHead);
|
||||
|
||||
for (int i = 0; i < _attachmentData.size(); i++) {
|
||||
if (_attachmentData[i].jointName.compare("Head", Qt::CaseInsensitive) == 0 ||
|
||||
|
|
|
@ -15,9 +15,7 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload {
|
|||
public:
|
||||
CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform);
|
||||
|
||||
#if defined(SKIN_COMP)
|
||||
using TransformType = Model::TransformComponents;
|
||||
#elif defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
using TransformType = Model::TransformDualQuaternion;
|
||||
#else
|
||||
using TransformType = glm::mat4;
|
||||
|
|
|
@ -104,12 +104,6 @@ void CauterizedModel::updateClusterMatrices() {
|
|||
_needsUpdateClusterMatrices = false;
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
|
||||
bool debug = false;
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "AJT: CauterizedModel::updateClusterMatrices(), url =" << _url;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)_meshStates.size(); i++) {
|
||||
Model::MeshState& state = _meshStates[i];
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
|
@ -117,12 +111,7 @@ void CauterizedModel::updateClusterMatrices() {
|
|||
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||
|
||||
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
||||
#if defined(SKIN_COMP)
|
||||
glm::mat4 m;
|
||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
|
||||
AnimPose p(m);
|
||||
state.clusterTransforms[j] = Model::TransformComponents(m);
|
||||
#elif defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
glm::mat4 m;
|
||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
|
||||
AnimPose p(m);
|
||||
|
@ -137,9 +126,9 @@ void CauterizedModel::updateClusterMatrices() {
|
|||
if (!_cauterizeBoneSet.empty()) {
|
||||
|
||||
static const glm::mat4 zeroScale(
|
||||
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
glm::vec4(0.0001f, 0.0f, 0.0f, 0.0f),
|
||||
glm::vec4(0.0f, 0.0001f, 0.0f, 0.0f),
|
||||
glm::vec4(0.0f, 0.0f, 0.0001f, 0.0f),
|
||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
auto cauterizeMatrix = _rig.getJointTransform(geometry.neckJointIndex) * zeroScale;
|
||||
|
||||
|
@ -155,12 +144,7 @@ void CauterizedModel::updateClusterMatrices() {
|
|||
jointMatrix = cauterizeMatrix;
|
||||
}
|
||||
|
||||
#if defined(SKIN_COMP)
|
||||
glm::mat4 m;
|
||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
|
||||
AnimPose p(m);
|
||||
state.clusterTransforms[j] = Model::TransformComponents(m);
|
||||
#elif defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
glm::mat4 m;
|
||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
|
||||
AnimPose p(m);
|
||||
|
@ -235,7 +219,7 @@ void CauterizedModel::updateRenderItems() {
|
|||
|
||||
Transform renderTransform = modelTransform;
|
||||
if (clusterTransforms.size() == 1) {
|
||||
#if defined(SKIN_COMP) || defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0].getMatrix()));
|
||||
#else
|
||||
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0]));
|
||||
|
@ -245,7 +229,7 @@ void CauterizedModel::updateRenderItems() {
|
|||
|
||||
renderTransform = modelTransform;
|
||||
if (clusterTransformsCauterized.size() == 1) {
|
||||
#if defined(SKIN_COMP) || defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0].getMatrix()));
|
||||
#else
|
||||
renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0]));
|
||||
|
|
|
@ -331,7 +331,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in
|
|||
updateTransform(transform, offsetTransform);
|
||||
Transform renderTransform = transform;
|
||||
if (state.clusterTransforms.size() == 1) {
|
||||
#if defined(SKIN_COMP) || defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0].getMatrix()));
|
||||
#else
|
||||
renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0]));
|
||||
|
@ -548,7 +548,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
|
|||
void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<TransformType>& clusterTransforms) {
|
||||
_adjustedLocalBound = _localBound;
|
||||
if (clusterTransforms.size() > 0) {
|
||||
#if defined(SKIN_COMP) || defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
_adjustedLocalBound.transform(clusterTransforms[0].getMatrix());
|
||||
#else
|
||||
_adjustedLocalBound.transform(clusterTransforms[0]);
|
||||
|
@ -556,7 +556,7 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector<Transform
|
|||
|
||||
for (int i = 1; i < (int)clusterTransforms.size(); ++i) {
|
||||
AABox clusterBound = _localBound;
|
||||
#if defined(SKIN_COMP) || defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
clusterBound.transform(clusterTransforms[i].getMatrix());
|
||||
#else
|
||||
clusterBound.transform(clusterTransforms[i]);
|
||||
|
|
|
@ -88,9 +88,7 @@ public:
|
|||
|
||||
void notifyLocationChanged() override;
|
||||
|
||||
#if defined(SKIN_COMP)
|
||||
using TransformType = Model::TransformComponents;
|
||||
#elif defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
using TransformType = Model::TransformDualQuaternion;
|
||||
#else
|
||||
using TransformType = glm::mat4;
|
||||
|
|
|
@ -276,7 +276,7 @@ void Model::updateRenderItems() {
|
|||
|
||||
Transform renderTransform = modelTransform;
|
||||
if (clusterTransforms.size() == 1) {
|
||||
#if defined(SKIN_COMP) || defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0].getMatrix()));
|
||||
#else
|
||||
renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0]));
|
||||
|
@ -1183,11 +1183,7 @@ void Model::updateClusterMatrices() {
|
|||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||
auto jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
||||
#if defined(SKIN_COMP)
|
||||
glm::mat4 mat;
|
||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, mat);
|
||||
state.clusterTransforms[j] = TransformComponents(mat);
|
||||
#elif defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
glm::mat4 mat;
|
||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, mat);
|
||||
state.clusterTransforms[j] = TransformDualQuaternion(mat);
|
||||
|
|
|
@ -256,43 +256,8 @@ public:
|
|||
int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; }
|
||||
bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; }
|
||||
|
||||
#if defined(SKIN_COMP)
|
||||
class TransformComponents {
|
||||
public:
|
||||
TransformComponents() {}
|
||||
TransformComponents(const glm::mat4& m) {
|
||||
AnimPose p(m);
|
||||
_scale.x = p.scale().x;
|
||||
_scale.y = p.scale().y;
|
||||
_scale.z = p.scale().z;
|
||||
_rot = p.rot();
|
||||
_trans.x = p.trans().x;
|
||||
_trans.y = p.trans().y;
|
||||
_trans.z = p.trans().z;
|
||||
}
|
||||
|
||||
TransformComponents(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans) {
|
||||
_scale.x = scale.x;
|
||||
_scale.y = scale.y;
|
||||
_scale.z = scale.z;
|
||||
_rot = rot;
|
||||
_trans.x = trans.x;
|
||||
_trans.y = trans.y;
|
||||
_trans.z = trans.z;
|
||||
}
|
||||
|
||||
glm::vec3 getScale() const { return glm::vec3(_scale); }
|
||||
glm::quat getRot() const { return _rot; }
|
||||
glm::vec3 getTrans() const { return glm::vec3(_trans); }
|
||||
glm::mat4 getMatrix() const { return createMatFromScaleQuatAndPos(getScale(), getRot(), getTrans()); };
|
||||
|
||||
protected:
|
||||
glm::vec4 _scale { 1.0f, 1.0f, 1.0f, 0.0f };
|
||||
glm::quat _rot { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||
glm::vec4 _trans { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
glm::vec4 _padding { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
};
|
||||
#elif defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
class TransformDualQuaternion {
|
||||
public:
|
||||
TransformDualQuaternion() {}
|
||||
|
@ -313,7 +278,7 @@ public:
|
|||
glm::quat getRot() const { return _dq.getRotation(); }
|
||||
glm::vec3 getTrans() const { return _dq.getTranslation(); }
|
||||
glm::mat4 getMatrix() const { return createMatFromScaleQuatAndPos(getScale(), getRot(), getTrans()); };
|
||||
public: // AJT: TODO FIX ME.
|
||||
protected:
|
||||
glm::vec4 _scale { 1.0f, 1.0f, 1.0f, 0.0f };
|
||||
DualQuaternion _dq;
|
||||
glm::vec4 _padding;
|
||||
|
@ -322,9 +287,7 @@ public:
|
|||
|
||||
class MeshState {
|
||||
public:
|
||||
#if defined(SKIN_COMP)
|
||||
std::vector<TransformComponents> clusterTransforms;
|
||||
#elif defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
std::vector<TransformDualQuaternion> clusterTransforms;
|
||||
#else
|
||||
std::vector<glm::mat4> clusterTransforms;
|
||||
|
|
|
@ -43,20 +43,19 @@ void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPositio
|
|||
vec3 sAccum = vec3(0.0, 0.0, 0.0);
|
||||
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 prevR = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];
|
||||
|
||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
||||
float clusterWeight = skinClusterWeight[i];
|
||||
|
||||
vec3 scale = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]);
|
||||
vec4 real = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]);
|
||||
vec4 imag = vec4(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2], clusterMatrix[2][3]);
|
||||
vec3 scale = vec3(clusterMatrix[0]);
|
||||
vec4 real = clusterMatrix[1];
|
||||
vec4 imag = clusterMatrix[2];
|
||||
|
||||
// to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.
|
||||
float dqClusterWeight = clusterWeight;
|
||||
if (i == 0) {
|
||||
prevR = real;
|
||||
} else if (dot(prevR, real) < 0) {
|
||||
if (dot(real, polarityReference) < 0) {
|
||||
dqClusterWeight = -clusterWeight;
|
||||
}
|
||||
|
||||
|
@ -108,20 +107,19 @@ void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inP
|
|||
vec3 sAccum = vec3(0.0, 0.0, 0.0);
|
||||
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 prevR = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];
|
||||
|
||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
||||
float clusterWeight = skinClusterWeight[i];
|
||||
|
||||
vec3 scale = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]);
|
||||
vec4 real = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]);
|
||||
vec4 imag = vec4(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2], clusterMatrix[2][3]);
|
||||
vec3 scale = vec3(clusterMatrix[0]);
|
||||
vec4 real = clusterMatrix[1];
|
||||
vec4 imag = clusterMatrix[2];
|
||||
|
||||
// to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.
|
||||
float dqClusterWeight = clusterWeight;
|
||||
if (i == 0) {
|
||||
prevR = real;
|
||||
} else if (dot(prevR, real) < 0) {
|
||||
if (dot(real, polarityReference) < 0) {
|
||||
dqClusterWeight = -clusterWeight;
|
||||
}
|
||||
|
||||
|
@ -174,20 +172,19 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v
|
|||
vec3 sAccum = vec3(0.0, 0.0, 0.0);
|
||||
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 iAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 prevR = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];
|
||||
|
||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
||||
float clusterWeight = skinClusterWeight[i];
|
||||
|
||||
vec3 scale = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]);
|
||||
vec4 real = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]);
|
||||
vec4 imag = vec4(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2], clusterMatrix[2][3]);
|
||||
vec3 scale = vec3(clusterMatrix[0]);
|
||||
vec4 real = clusterMatrix[1];
|
||||
vec4 imag = clusterMatrix[2];
|
||||
|
||||
// to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.
|
||||
float dqClusterWeight = clusterWeight;
|
||||
if (i == 0) {
|
||||
prevR = real;
|
||||
} else if (dot(prevR, real) < 0) {
|
||||
if (dot(real, polarityReference) < 0) {
|
||||
dqClusterWeight = -clusterWeight;
|
||||
}
|
||||
|
||||
|
@ -326,54 +323,4 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v
|
|||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// ORIGINAL
|
||||
void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {
|
||||
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
||||
float clusterWeight = skinClusterWeight[i];
|
||||
newPosition += clusterMatrix * inPosition * clusterWeight;
|
||||
}
|
||||
|
||||
skinnedPosition = newPosition;
|
||||
}
|
||||
|
||||
void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,
|
||||
out vec4 skinnedPosition, out vec3 skinnedNormal) {
|
||||
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
||||
float clusterWeight = skinClusterWeight[i];
|
||||
newPosition += clusterMatrix * inPosition * clusterWeight;
|
||||
newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;
|
||||
}
|
||||
|
||||
skinnedPosition = newPosition;
|
||||
skinnedNormal = newNormal.xyz;
|
||||
}
|
||||
|
||||
void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,
|
||||
out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {
|
||||
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
||||
float clusterWeight = skinClusterWeight[i];
|
||||
newPosition += clusterMatrix * inPosition * clusterWeight;
|
||||
newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;
|
||||
newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;
|
||||
}
|
||||
|
||||
skinnedPosition = newPosition;
|
||||
skinnedNormal = newNormal.xyz;
|
||||
skinnedTangent = newTangent.xyz;
|
||||
}
|
||||
*/
|
||||
|
||||
<@endif@>
|
||||
|
|
|
@ -58,11 +58,7 @@ void SoftAttachmentModel::updateClusterMatrices() {
|
|||
} else {
|
||||
jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
||||
}
|
||||
#if defined(SKIN_COMP)
|
||||
glm::mat4 m;
|
||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
|
||||
state.clusterTransforms[j] = Model::TransformComponents(m);
|
||||
#elif defined(SKIN_DQ)
|
||||
#if defined(SKIN_DQ)
|
||||
glm::mat4 m;
|
||||
glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m);
|
||||
state.clusterTransforms[j] = Model::TransformDualQuaternion(m);
|
||||
|
|
|
@ -63,18 +63,15 @@ glm::vec3 DualQuaternion::xformVector(const glm::vec3& rhs) const {
|
|||
return _real * rhs;
|
||||
}
|
||||
|
||||
// AJT: UNTESTED
|
||||
DualQuaternion DualQuaternion::inverse() const {
|
||||
glm::quat invReal = glm::inverse(_real);
|
||||
return DualQuaternion(invReal, - invReal * _imag * invReal);
|
||||
}
|
||||
|
||||
// AJT: UNTESTED
|
||||
DualQuaternion DualQuaternion::conjugate() const {
|
||||
return DualQuaternion(glm::conjugate(_real), glm::conjugate(_imag));
|
||||
}
|
||||
|
||||
// AJT: UNTESTED
|
||||
float DualQuaternion::length() const {
|
||||
float dot = this->dot(*this);
|
||||
return sqrtf(dot);
|
||||
|
|
Loading…
Reference in a new issue