Remove (almost) all references to pRenderer (#651)
Remove all references to pRenderer, except from the DebugDraw and LyShine Gems that are still being updated.
This commit is contained in:
@@ -1,769 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ArcBall.h"
|
||||
|
||||
bool CArcBall3D::ArcControl(const Matrix34& reference, const Ray& ray, uint32 mouseleft)
|
||||
{
|
||||
RotControl <<= 1;
|
||||
|
||||
if (mouseleft)
|
||||
{
|
||||
RotControl |= 1;
|
||||
}
|
||||
|
||||
Quat WObjectRotation = Quat(reference * Matrix34(ObjectRotation));
|
||||
Matrix34 WMat = reference * Matrix34(Matrix33(DragRotation * ObjectRotation), sphere.center);
|
||||
Sphere WSphere(WMat.GetTranslation(), sphere.radius);
|
||||
|
||||
Mouse_CutFlag = 0;
|
||||
Vec3 Mouse_CutOn3DSphere(0, 0, 0);
|
||||
Mouse_CutOnUnitSphere = Vec3(ZERO);
|
||||
Mouse_CutFlag = Intersect::Ray_SphereFirst(ray, WSphere, Mouse_CutOn3DSphere);
|
||||
|
||||
if (Mouse_CutFlag)
|
||||
{
|
||||
Mouse_CutOnUnitSphere = WObjectRotation.GetInverted() * (Mouse_CutOn3DSphere - WSphere.center).GetNormalized();
|
||||
}
|
||||
|
||||
if (RotControl & 3)
|
||||
{
|
||||
if (Mouse_CutFlag)
|
||||
{
|
||||
if ((RotControl & 3) == 0x01)
|
||||
{
|
||||
Mouse_CutFlagStart = 1;
|
||||
LineStart3D = Mouse_CutOnUnitSphere;
|
||||
AxisSnap = 0;
|
||||
|
||||
Matrix33 bym33;
|
||||
|
||||
//get the distance to the axis
|
||||
f32 xdist = fabsf(Mouse_CutOnUnitSphere.x);
|
||||
f32 ydist = fabsf(Mouse_CutOnUnitSphere.y);
|
||||
f32 zdist = fabsf(Mouse_CutOnUnitSphere.z);
|
||||
|
||||
//if to close to an axis-crossing, disable axis choosing
|
||||
if ((xdist < CrossDist) && (zdist < CrossDist))
|
||||
{
|
||||
xdist = 1.0f;
|
||||
ydist = 1.0f;
|
||||
zdist = 1.0f;
|
||||
}
|
||||
if ((xdist < CrossDist) && (ydist < CrossDist))
|
||||
{
|
||||
xdist = 1.0f;
|
||||
ydist = 1.0f;
|
||||
zdist = 1.0f;
|
||||
}
|
||||
if ((ydist < CrossDist) && (zdist < CrossDist))
|
||||
{
|
||||
xdist = 1.0f;
|
||||
ydist = 1.0f;
|
||||
zdist = 1.0f;
|
||||
}
|
||||
|
||||
//check snap with YZ-plane
|
||||
if (xdist < AxisDist)
|
||||
{
|
||||
bym33.SetIdentity();
|
||||
|
||||
if ((LineStart3D.x) || (LineStart3D.z))
|
||||
{
|
||||
Vec3 n = Vec3(LineStart3D.x, 0, LineStart3D.z).GetNormalized();
|
||||
bym33.SetRotationY(acos_tpl(fabsf(n.z)));
|
||||
}
|
||||
|
||||
Vec3 SnapLineStart3D = bym33 * Vec3(fabsf(LineStart3D.x), LineStart3D.y, -fabsf(LineStart3D.z));
|
||||
|
||||
if (LineStart3D.z > 0.0f)
|
||||
{
|
||||
SnapLineStart3D.z = -SnapLineStart3D.z;
|
||||
}
|
||||
|
||||
LineStart3D = SnapLineStart3D;
|
||||
AxisSnap = 1;
|
||||
}
|
||||
|
||||
//check snap with XZ-plane
|
||||
if (ydist < AxisDist)
|
||||
{
|
||||
bym33.SetIdentity();
|
||||
|
||||
if ((LineStart3D.y) || (LineStart3D.z))
|
||||
{
|
||||
Vec3 bn_xz = Vec3(0, LineStart3D.y, LineStart3D.z).GetNormalized();
|
||||
bym33.SetRotationX(-acos_tpl(fabsf(bn_xz.z)));
|
||||
}
|
||||
|
||||
Vec3 SnapLineStart3D = bym33 * Vec3((LineStart3D.x), fabsf(LineStart3D.y), -fabsf(LineStart3D.z));
|
||||
|
||||
if (LineStart3D.z > 0.0f)
|
||||
{
|
||||
SnapLineStart3D.z = -SnapLineStart3D.z;
|
||||
}
|
||||
|
||||
LineStart3D = SnapLineStart3D;
|
||||
AxisSnap = 2;
|
||||
}
|
||||
|
||||
//check snap with XY-plane
|
||||
if (zdist < AxisDist)
|
||||
{
|
||||
bym33.SetIdentity();
|
||||
|
||||
if ((LineStart3D.x) || (LineStart3D.z))
|
||||
{
|
||||
Vec3 bn_xz = Vec3(LineStart3D.x, 0, LineStart3D.z).GetNormalized();
|
||||
bym33.SetRotationY(-acos_tpl(fabsf(bn_xz.x)));
|
||||
}
|
||||
|
||||
Vec3 SnapLineStart3D = bym33 * Vec3(fabsf(LineStart3D.x), LineStart3D.y, -fabsf(LineStart3D.z));
|
||||
|
||||
if (LineStart3D.x < 0.0f)
|
||||
{
|
||||
SnapLineStart3D.x = -SnapLineStart3D.x;
|
||||
}
|
||||
|
||||
LineStart3D = SnapLineStart3D;
|
||||
AxisSnap = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if ((RotControl & 3) == 0x03)
|
||||
{
|
||||
ArcRotation();
|
||||
}
|
||||
|
||||
if ((RotControl & 3) == 0x02)
|
||||
{
|
||||
ObjectRotation = (DragRotation * ObjectRotation).GetNormalized();
|
||||
DragRotation.SetIdentity();
|
||||
Mouse_CutFlagStart = 0;
|
||||
LineStart3D = Vec3(0, -1, 0);
|
||||
AxisSnap = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3 ClostestPointOnLine;
|
||||
IntersectSphereLineSegment(WSphere, ray.origin, ray.origin + ray.direction * 1000.0f, ClostestPointOnLine);
|
||||
|
||||
Mouse_CutOn3DSphere = ((ClostestPointOnLine - WSphere.center).GetNormalized() * WSphere.radius) + WSphere.center;
|
||||
Mouse_CutOnUnitSphere = WObjectRotation.GetInverted() * (Mouse_CutOn3DSphere - WSphere.center).GetNormalized();
|
||||
|
||||
if ((RotControl & 3) == 0x01)
|
||||
{
|
||||
LineStart3D = Mouse_CutOnUnitSphere;
|
||||
Mouse_CutFlagStart = 0;
|
||||
AxisSnap = 0;
|
||||
}
|
||||
|
||||
if ((RotControl & 3) == 0x03)
|
||||
{
|
||||
ArcRotation();
|
||||
}
|
||||
|
||||
if ((RotControl & 3) == 0x02)
|
||||
{
|
||||
ObjectRotation = (DragRotation * ObjectRotation).GetNormalized();
|
||||
DragRotation.SetIdentity();
|
||||
Mouse_CutFlagStart = 0;
|
||||
LineStart3D = Vec3(0, -1, 0);
|
||||
AxisSnap = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CArcBall3D::ArcRotation()
|
||||
{
|
||||
Vec3 rv;
|
||||
f32 gradius = 0;
|
||||
f32 distance_YZ = 0;
|
||||
f32 bias = 0;
|
||||
f32 cosine = 0;
|
||||
Vec3 XYVector;
|
||||
|
||||
DragRotation.SetIdentity();
|
||||
|
||||
//first we calculate an ordinary drag-quaternion
|
||||
cosine = (LineStart3D | Mouse_CutOnUnitSphere);
|
||||
|
||||
if (fabsf(cosine) < 0.99999f)
|
||||
{
|
||||
DragRotation.SetRotationAA(acos_tpl(cosine), (LineStart3D % Mouse_CutOnUnitSphere).GetNormalized());
|
||||
}
|
||||
|
||||
if (AxisSnap == 1)
|
||||
{
|
||||
//m_ButtonArcRotate an UpVector with our drag-quaternion
|
||||
rv = (DragRotation) * Vec3(0, -1, 0);
|
||||
DragRotation.SetIdentity();
|
||||
|
||||
//project rotated UpVector into XY_Plane (this is a simple y_axis rotation)
|
||||
Matrix33 ym33;
|
||||
ym33.SetIdentity();
|
||||
|
||||
if ((rv.x) || (rv.z))
|
||||
{
|
||||
Vec3 n_xz = Vec3(rv.x, 0, rv.z).GetNormalized();
|
||||
ym33.SetRotationY(-acos_tpl(fabsf(n_xz.z)));
|
||||
}
|
||||
|
||||
XYVector = ym33 * Vec3(-fabsf(rv.x), rv.y, -fabsf(rv.z));
|
||||
|
||||
//find the rotation direction around z-axis
|
||||
if (rv.z > 0)
|
||||
{
|
||||
XYVector.z = -XYVector.z;
|
||||
}
|
||||
|
||||
//calculate the xy-constrained quaternion
|
||||
cosine = (Vec3(0, -1, 0) | XYVector);
|
||||
|
||||
if (fabsf(cosine) < 0.99999f)
|
||||
{
|
||||
gradius = Vec3(rv.x, 0, rv.z).GetLength();
|
||||
distance_YZ = fabsf(rv.z);
|
||||
bias = distance_YZ / gradius;
|
||||
DragRotation.SetRotationAA(acos_tpl(cosine) * bias, (Vec3(0, -1, 0) % XYVector).GetNormalized());
|
||||
}
|
||||
}
|
||||
|
||||
if (AxisSnap == 2)
|
||||
{
|
||||
//m_ButtonArcRotate an UpVector with our DRAG-QUATERNION
|
||||
rv = DragRotation * Vec3(-1, 0, 0);
|
||||
DragRotation.SetIdentity();
|
||||
|
||||
//project rotated UpVector into XY_Plane (this is a simple x_axis rotation)
|
||||
Matrix33 ym33;
|
||||
ym33.SetIdentity();
|
||||
|
||||
if ((rv.y) || (rv.z))
|
||||
{
|
||||
Vec3 n_xz = Vec3(0, rv.y, rv.z).GetNormalized();
|
||||
ym33.SetRotationX(-acos_tpl(fabsf(n_xz.z)));
|
||||
}
|
||||
|
||||
XYVector = ym33 * Vec3((rv.x), fabsf(rv.y), -fabsf(rv.z));
|
||||
|
||||
//find the rotation direction around y-axis
|
||||
if (rv.z > 0)
|
||||
{
|
||||
XYVector.z = -XYVector.z;
|
||||
}
|
||||
|
||||
//calculate the xz-constrained quaternion
|
||||
cosine = (Vec3(-1, 0, 0) | XYVector);
|
||||
|
||||
if (fabsf(cosine) < 0.99999f)
|
||||
{
|
||||
gradius = Vec3(0, rv.y, rv.z).GetLength();
|
||||
distance_YZ = fabsf(rv.z);
|
||||
bias = distance_YZ / gradius;
|
||||
DragRotation.SetRotationAA(acos_tpl(cosine) * bias, (Vec3(-1, 0, 0) % XYVector).GetNormalized());
|
||||
}
|
||||
}
|
||||
|
||||
if (AxisSnap == 3)
|
||||
{
|
||||
//m_ButtonArcRotate an UpVector with our DRAG-QUATERNION
|
||||
rv = DragRotation * Vec3(0, -1, 0);
|
||||
DragRotation.SetIdentity();
|
||||
|
||||
//project rotated UpVector into XY_Plane (this is a simple y_axis rotation)
|
||||
Matrix33 ym33;
|
||||
|
||||
ym33.SetIdentity();
|
||||
|
||||
if ((rv.x) || (rv.z))
|
||||
{
|
||||
Vec3 n_xz = Vec3(rv.x, 0, rv.z).GetNormalized();
|
||||
ym33.SetRotationY(-acos_tpl(fabsf(n_xz.x)));
|
||||
}
|
||||
|
||||
XYVector = ym33 * Vec3(fabsf(rv.x), rv.y, -fabsf(rv.z));
|
||||
|
||||
//find the rotation direction around z-axis
|
||||
if (rv.x < 0)
|
||||
{
|
||||
XYVector.x = -XYVector.x;
|
||||
}
|
||||
|
||||
//calculate the xy-constrained quaternion
|
||||
cosine = (Vec3(0, -1, 0) | XYVector);
|
||||
|
||||
if (fabsf(cosine) < 0.99999f)
|
||||
{
|
||||
gradius = Vec3(rv.x, 0, rv.z).GetLength();
|
||||
distance_YZ = fabsf(rv.x);
|
||||
bias = distance_YZ / gradius;
|
||||
DragRotation.SetRotationAA(acos_tpl(cosine) * bias, (Vec3(0, -1, 0) % XYVector).GetNormalized());
|
||||
}
|
||||
}
|
||||
|
||||
//BINGO!!!! the final drag quaternion
|
||||
DragRotation = ObjectRotation * DragRotation * ObjectRotation.GetInverted();
|
||||
}
|
||||
|
||||
uint32 CArcBall3D::IntersectSphereLineSegment(const Sphere& sphere, const Vec3& LineStart, const Vec3& LineEnd, Vec3& I)
|
||||
{
|
||||
//this is the code to produce a real z-rotation!
|
||||
Vec3 LineDir = (LineEnd - LineStart).GetNormalized();
|
||||
Vec3 ShereCenterDir = (sphere.center - LineStart).GetNormalized();
|
||||
f32 LengthToSphereCenter = (sphere.center - LineStart).GetLength();
|
||||
|
||||
f32 cosine = (ShereCenterDir | LineDir);
|
||||
|
||||
//this vector is perpendicular to the vector "ShereCenterDir"
|
||||
Vec3 PerpVector = LengthToSphereCenter / cosine * LineDir + LineStart;
|
||||
Vec3 PerpVectorOnSphere = ((PerpVector - sphere.center).GetNormalized() * sphere.radius) + sphere.center;
|
||||
I = PerpVectorOnSphere;
|
||||
|
||||
{
|
||||
//find closest point on Lineseg
|
||||
Vec3 LineDir2 = (LineEnd - LineStart).GetNormalized();
|
||||
f32 proj = LineDir2 | (sphere.center - LineStart);
|
||||
I = LineDir2 * proj + LineStart;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CArcBall3D::DrawSphere(const Matrix34& reference, const CCamera& cam, IRenderAuxGeom* pRenderer)
|
||||
{
|
||||
f32 thicknessX = 1.0f;
|
||||
f32 thicknessY = 1.0f;
|
||||
f32 thicknessZ = 1.0f;
|
||||
|
||||
uint32 start;
|
||||
Vec3 Vertices3D[64 * 32];
|
||||
Vec3 sVertices3D[64 * 32];
|
||||
Vec3 tVertices3D[64 * 32];
|
||||
uint32 c;
|
||||
|
||||
Matrix34 WMat = reference * Matrix34(Matrix33(DragRotation * ObjectRotation), sphere.center);
|
||||
Quat WObjectRotation = Quat(reference * Matrix34(ObjectRotation));
|
||||
Quat WRotation = Quat(reference * Matrix34(DragRotation * ObjectRotation));
|
||||
Sphere WSphere(WMat.GetTranslation(), sphere.radius);
|
||||
|
||||
SAuxGeomRenderFlags renderFlags(e_Def3DPublicRenderflags);
|
||||
renderFlags.SetDepthWriteFlag(e_DepthWriteOff);
|
||||
renderFlags.SetFillMode(e_FillModeSolid);
|
||||
|
||||
//------------------------------------------------------------------------------------------------------
|
||||
|
||||
uint32 s = 0;
|
||||
uint32 t = 0;
|
||||
Vec3 CamPos = cam.GetPosition();
|
||||
|
||||
renderFlags.SetAlphaBlendMode(e_AlphaAdditive);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
pRenderer->DrawSphere(WSphere.center, WSphere.radius, RGBA8(0x3f, 0x3f, 0x3f, 0x00));
|
||||
|
||||
ColorB col;
|
||||
f32 xdist = fabsf(Mouse_CutOnUnitSphere.x);
|
||||
f32 ydist = fabsf(Mouse_CutOnUnitSphere.y);
|
||||
f32 zdist = fabsf(Mouse_CutOnUnitSphere.z);
|
||||
|
||||
if ((xdist < CrossDist) && (zdist < CrossDist))
|
||||
{
|
||||
xdist = 1.0f;
|
||||
ydist = 1.0f;
|
||||
zdist = 1.0f;
|
||||
}
|
||||
if ((xdist < CrossDist) && (ydist < CrossDist))
|
||||
{
|
||||
xdist = 1.0f;
|
||||
ydist = 1.0f;
|
||||
zdist = 1.0f;
|
||||
}
|
||||
if ((ydist < CrossDist) && (zdist < CrossDist))
|
||||
{
|
||||
xdist = 1.0f;
|
||||
ydist = 1.0f;
|
||||
zdist = 1.0f;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// draw circle around X-axis
|
||||
//----------------------------------------------------------------------------------
|
||||
thicknessX = 1.0f;
|
||||
|
||||
if (AxisSnap == 0)
|
||||
{
|
||||
if (Mouse_CutFlag)
|
||||
{
|
||||
if (xdist < AxisDist)
|
||||
{
|
||||
thicknessX = 5.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (AxisSnap == 1)
|
||||
{
|
||||
thicknessX = 5.0f;
|
||||
}
|
||||
|
||||
c = 0;
|
||||
|
||||
for (f32 cz = 0; cz < (gf_PI * 2); cz = cz + (2 * gf_PI / 256.0f), ++c)
|
||||
{
|
||||
Vertices3D[c] = WMat * (Vec3(0, -cosf(cz), sinf(cz)) * WSphere.radius);
|
||||
}
|
||||
|
||||
assert(c == 0x100);
|
||||
|
||||
for (start = 0; start < c; ++start)
|
||||
{
|
||||
Vec3 p0 = Vertices3D[(start + 0) & 0xff];
|
||||
f32 dot0 = (p0 - CamPos) | (p0 - WSphere.center);
|
||||
Vec3 p1 = Vertices3D[(start + 1) & 0xff];
|
||||
f32 dot1 = (p1 - CamPos) | (p1 - WSphere.center);
|
||||
|
||||
if ((dot0 < 0) && !(dot1 < 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s = 0;
|
||||
t = 0;
|
||||
start = (start + 1) & 0xff;
|
||||
|
||||
for (uint32 i = 0; i < c; ++i)
|
||||
{
|
||||
Vec3 p = Vertices3D[start];
|
||||
f32 dot = (p - CamPos) | (p - WSphere.center);
|
||||
|
||||
if (dot < 0)
|
||||
{
|
||||
sVertices3D[s] = p;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tVertices3D[t] = p;
|
||||
t++;
|
||||
}
|
||||
|
||||
start = (start + 1) & 0xff;
|
||||
}
|
||||
|
||||
renderFlags.SetAlphaBlendMode(e_AlphaNone);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
|
||||
if (s > 2)
|
||||
{
|
||||
pRenderer->DrawPolyline(sVertices3D, s, 0, RGBA8(0xff, 0x12, 0x12, 0x00), thicknessX);
|
||||
}
|
||||
|
||||
renderFlags.SetAlphaBlendMode(e_AlphaAdditive);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
|
||||
if (t > 2)
|
||||
{
|
||||
pRenderer->DrawPolyline(tVertices3D, t, 0, RGBA8(0x1f, 0x07, 0x07, 0x00), thicknessX);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// draw circle around Y-axis
|
||||
//----------------------------------------------------------------------------------
|
||||
thicknessY = 1.0f;
|
||||
|
||||
if (AxisSnap == 0)
|
||||
{
|
||||
if (Mouse_CutFlag)
|
||||
{
|
||||
if (ydist < AxisDist)
|
||||
{
|
||||
thicknessY = 5.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (AxisSnap == 2)
|
||||
{
|
||||
thicknessY = 5.0f;
|
||||
}
|
||||
|
||||
c = 0;
|
||||
|
||||
for (f32 cz = 0; cz < (gf_PI * 2); cz = cz + (2 * gf_PI / 256.0f), ++c)
|
||||
{
|
||||
Vertices3D[c] = WMat * (Vec3(-cosf(cz), 0, sinf(cz)) * WSphere.radius);
|
||||
}
|
||||
|
||||
assert(c == 0x100);
|
||||
|
||||
for (start = 0; start < c; ++start)
|
||||
{
|
||||
Vec3 p0 = Vertices3D[(start + 0) & 0xff];
|
||||
f32 dot0 = (p0 - CamPos) | (p0 - WSphere.center);
|
||||
Vec3 p1 = Vertices3D[(start + 1) & 0xff];
|
||||
f32 dot1 = (p1 - CamPos) | (p1 - WSphere.center);
|
||||
|
||||
if ((dot0 < 0) && !(dot1 < 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s = 0;
|
||||
t = 0;
|
||||
start = (start + 1) & 0xff;
|
||||
|
||||
for (uint32 i = 0; i < c; ++i)
|
||||
{
|
||||
Vec3 p = Vertices3D[start];
|
||||
f32 dot = (p - CamPos) | (p - WSphere.center);
|
||||
if (dot < 0)
|
||||
{
|
||||
sVertices3D[s] = p;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tVertices3D[t] = p;
|
||||
t++;
|
||||
}
|
||||
|
||||
start = (start + 1) & 0xff;
|
||||
}
|
||||
|
||||
renderFlags.SetAlphaBlendMode(e_AlphaNone);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
|
||||
if (s > 2)
|
||||
{
|
||||
pRenderer->DrawPolyline(sVertices3D, s, 0, RGBA8(0x12, 0xff, 0x12, 0x00), thicknessY);
|
||||
}
|
||||
|
||||
renderFlags.SetAlphaBlendMode(e_AlphaAdditive);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
|
||||
if (t > 2)
|
||||
{
|
||||
pRenderer->DrawPolyline(tVertices3D, t, 0, RGBA8(0x07, 0x1f, 0x07, 0x00), thicknessY);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// draw circle around Z-axis
|
||||
//----------------------------------------------------------------------------------
|
||||
thicknessZ = 1.0f;
|
||||
|
||||
if (AxisSnap == 0)
|
||||
{
|
||||
if (Mouse_CutFlag)
|
||||
{
|
||||
if (zdist < AxisDist)
|
||||
{
|
||||
thicknessZ = 5.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (AxisSnap == 3)
|
||||
{
|
||||
thicknessZ = 5.0f;
|
||||
}
|
||||
|
||||
c = 0;
|
||||
for (f32 cz = 0; cz < (gf_PI * 2); cz = cz + (2 * gf_PI / 256.0f), ++c)
|
||||
{
|
||||
Vertices3D[c] = WMat * (Vec3(sinf(cz), -cosf(cz), 0) * WSphere.radius);
|
||||
}
|
||||
|
||||
assert(c == 0x100);
|
||||
|
||||
for (start = 0; start < c; ++start)
|
||||
{
|
||||
Vec3 p0 = Vertices3D[(start + 0) & 0xff];
|
||||
f32 dot0 = (p0 - CamPos) | (p0 - WSphere.center);
|
||||
Vec3 p1 = Vertices3D[(start + 1) & 0xff];
|
||||
f32 dot1 = (p1 - CamPos) | (p1 - WSphere.center);
|
||||
|
||||
if ((dot0 < 0) && !(dot1 < 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s = 0;
|
||||
t = 0;
|
||||
start = (start + 1) & 0xff;
|
||||
|
||||
for (uint32 i = 0; i < c; ++i)
|
||||
{
|
||||
Vec3 p = Vertices3D[start];
|
||||
f32 dot = (p - CamPos) | (p - WSphere.center);
|
||||
|
||||
if (dot < 0)
|
||||
{
|
||||
sVertices3D[s] = p;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tVertices3D[t] = p;
|
||||
t++;
|
||||
}
|
||||
|
||||
start = (start + 1) & 0xff;
|
||||
}
|
||||
|
||||
renderFlags.SetAlphaBlendMode(e_AlphaNone);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
|
||||
if (s > 2)
|
||||
{
|
||||
pRenderer->DrawPolyline(sVertices3D, s, 0, RGBA8(0x12, 0x12, 0xff, 0x00), thicknessZ);
|
||||
}
|
||||
|
||||
renderFlags.SetAlphaBlendMode(e_AlphaAdditive);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
|
||||
if (t > 2)
|
||||
{
|
||||
pRenderer->DrawPolyline(tVertices3D, t, 0, RGBA8(0x07, 0x07, 0x1f, 0x00), thicknessZ);
|
||||
}
|
||||
|
||||
uint32 v;
|
||||
|
||||
Vec3 VBuffer[1000];
|
||||
ColorB CBuffer[1000];
|
||||
|
||||
if ((RotControl & 3) == 3)
|
||||
{
|
||||
Vec3 Blue = WObjectRotation * LineStart3D;
|
||||
Vec3 Red = WObjectRotation * Mouse_CutOnUnitSphere;
|
||||
|
||||
VBuffer[0] = Vec3(0, 0, 0);
|
||||
CBuffer[0] = RGBA8(0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
VBuffer[1] = Blue;
|
||||
CBuffer[1] = RGBA8(0x00, 0x00, 0xff, 0x00);
|
||||
|
||||
VBuffer[102] = Red;
|
||||
CBuffer[102] = RGBA8(0xff, 0x00, 0x00, 0x00);
|
||||
|
||||
for (v = 0; v < 100; ++v)
|
||||
{
|
||||
f32 t0 = (1.0f / 101.0f * v) + 1.0f / 101.0f;
|
||||
|
||||
VBuffer[v + 2] = Vec3::CreateSlerp(Blue, Red, t0);
|
||||
|
||||
f32 t1 = (1.0f / 101.0f * v);
|
||||
|
||||
CBuffer[v + 2].b = uint8((1.0f - t1) * CBuffer[1].b + t1 * CBuffer[102].b);
|
||||
CBuffer[v + 2].g = uint8((1.0f - t1) * CBuffer[1].g + t1 * CBuffer[102].g);
|
||||
CBuffer[v + 2].r = uint8((1.0f - t1) * CBuffer[1].r + t1 * CBuffer[102].r);
|
||||
}
|
||||
|
||||
for (v = 0; v < 103; ++v)
|
||||
{
|
||||
VBuffer[v] = VBuffer[v] * WSphere.radius + WSphere.center;
|
||||
}
|
||||
|
||||
if (AxisSnap == 0)
|
||||
{
|
||||
SAuxGeomRenderFlags renderFlags2(e_Def3DPublicRenderflags);
|
||||
|
||||
renderFlags2.SetFillMode(e_FillModeSolid);
|
||||
renderFlags2.SetAlphaBlendMode(e_AlphaAdditive);
|
||||
pRenderer->SetRenderFlags(renderFlags2);
|
||||
|
||||
for (v = 0; v < 100; ++v)
|
||||
{
|
||||
pRenderer->DrawTriangle(VBuffer[0], CBuffer[0], VBuffer[v + 1], CBuffer[v + 1], VBuffer[v + 2], CBuffer[v + 2]);
|
||||
pRenderer->DrawTriangle(VBuffer[0], CBuffer[0], VBuffer[v + 2], CBuffer[v + 2], VBuffer[v + 1], CBuffer[v + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AxisSnap)
|
||||
{
|
||||
//project vector into the xy-plane
|
||||
VBuffer[0] = Vec3(0, 0, 0);
|
||||
CBuffer[0] = RGBA8(0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
VBuffer[1] = WObjectRotation * LineStart3D;
|
||||
CBuffer[1] = RGBA8(0x12, 0x1f, 0x12, 0x00);
|
||||
|
||||
VBuffer[102] = WRotation * LineStart3D;
|
||||
CBuffer[102] = RGBA8(0x22, 0x7f, 0x22, 0x00);
|
||||
|
||||
ColorB c0 = CBuffer[1];
|
||||
ColorB c1 = CBuffer[102];
|
||||
|
||||
for (v = 0; v < 100; ++v)
|
||||
{
|
||||
f32 t0 = (1.0f / 101.0f * v) + 1.0f / 101.0f;
|
||||
|
||||
VBuffer[v + 2] = Vec3::CreateSlerp(VBuffer[1], VBuffer[102], t0);
|
||||
|
||||
f32 t1 = (1.0f / 101.0f * v);
|
||||
CBuffer[v + 2].r = uint8((1.0f - t1) * c0.r + t1 * c1.r);
|
||||
CBuffer[v + 2].g = uint8((1.0f - t1) * c0.g + t1 * c1.g);
|
||||
CBuffer[v + 2].b = uint8((1.0f - t1) * c0.b + t1 * c1.b);
|
||||
}
|
||||
|
||||
for (v = 0; v < 103; ++v)
|
||||
{
|
||||
VBuffer[v] = VBuffer[v] * WSphere.radius + WSphere.center;
|
||||
}
|
||||
|
||||
SAuxGeomRenderFlags renderFlags2(e_Def3DPublicRenderflags);
|
||||
renderFlags2.SetFillMode(e_FillModeSolid);
|
||||
renderFlags2.SetAlphaBlendMode(e_AlphaAdditive);
|
||||
pRenderer->SetRenderFlags(renderFlags2);
|
||||
|
||||
for (v = 0; v < 100; ++v)
|
||||
{
|
||||
pRenderer->DrawTriangle(VBuffer[0], CBuffer[0], VBuffer[v + 1], CBuffer[v + 1], VBuffer[v + 2], CBuffer[v + 2]);
|
||||
pRenderer->DrawTriangle(VBuffer[0], CBuffer[0], VBuffer[v + 2], CBuffer[v + 2], VBuffer[v + 1], CBuffer[v + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
renderFlags = e_Def3DPublicRenderflags;
|
||||
renderFlags.SetFillMode(e_FillModeSolid);
|
||||
renderFlags.SetAlphaBlendMode(e_AlphaNone);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
|
||||
#define CROSS (0.25f)
|
||||
|
||||
Vec3 rmin = WMat * Vec3(0, 0.0f, 0.0f);
|
||||
Vec3 rmax = WMat * Vec3(CROSS, 0.0f, 0.0f);
|
||||
|
||||
pRenderer->DrawLine(rmin, RGBA8(0xff, 0x00, 0x00, 0x00), rmax, RGBA8(0xff, 0x7f, 0x7f, 0x00), thicknessX);
|
||||
|
||||
Vec3 gmin = WMat * Vec3(0.0f, 0, 0.0f);
|
||||
Vec3 gmax = WMat * Vec3(0.0f, CROSS, 0.0f);
|
||||
|
||||
pRenderer->DrawLine(gmin, RGBA8(0x00, 0xff, 0x00, 0x00), gmax, RGBA8(0x7f, 0xff, 0x7f, 0x00), thicknessY);
|
||||
|
||||
Vec3 bmin = WMat * Vec3(0.0f, 0.0f, 0);
|
||||
Vec3 bmax = WMat * Vec3(0.0f, 0.0f, CROSS);
|
||||
|
||||
pRenderer->DrawLine(bmin, RGBA8(0x00, 0x00, 0xff, 0x00), bmax, RGBA8(0x7f, 0x7f, 0xff, 0x00), thicknessZ);
|
||||
renderFlags.SetDepthWriteFlag(e_DepthWriteOn);
|
||||
pRenderer->SetRenderFlags(renderFlags);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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_EDITOR_UTIL_ARCBALL_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_ARCBALL_H
|
||||
#pragma once
|
||||
#include <Cry_Math.h>
|
||||
#include <Cry_Color.h>
|
||||
|
||||
#define CrossDist (0.05f)
|
||||
#define AxisDist (0.05f)
|
||||
|
||||
class SANDBOX_API CArcBall3D
|
||||
{
|
||||
public:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
uint32 RotControl;
|
||||
Sphere sphere;
|
||||
uint32 Mouse_CutFlag;
|
||||
uint32 Mouse_CutFlagStart;
|
||||
uint32 AxisSnap;
|
||||
Vec3 LineStart3D;
|
||||
Vec3 Mouse_CutOnUnitSphere;
|
||||
Quat DragRotation;
|
||||
Quat ObjectRotation;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
CArcBall3D()
|
||||
{
|
||||
InitArcBall();
|
||||
};
|
||||
|
||||
void InitArcBall()
|
||||
{
|
||||
RotControl = 0;
|
||||
sphere(Vec3(ZERO), 0.25f);
|
||||
Mouse_CutFlag = 0;
|
||||
Mouse_CutOnUnitSphere(0, 0, 0);
|
||||
LineStart3D(0, -1, 0);
|
||||
AxisSnap = 0;
|
||||
DragRotation.SetIdentity();
|
||||
ObjectRotation.SetIdentity();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// ArcControl
|
||||
// Returns true if the rotation has changed
|
||||
//---------------------------------------------------------------
|
||||
bool ArcControl(const Matrix34& reference, const Ray& ray, uint32 mouseleft);
|
||||
void ArcRotation();
|
||||
void DrawSphere(const Matrix34& reference, const CCamera& cam, struct IRenderAuxGeom* pRenderer);
|
||||
static uint32 IntersectSphereLineSegment(const Sphere& s, const Vec3& LineStart, const Vec3& LineEnd, Vec3& I);
|
||||
};
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_ARCBALL_H
|
||||
@@ -1,251 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "CubemapUtils.h"
|
||||
|
||||
// Qt
|
||||
#include <QAbstractListModel>
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
// Editor
|
||||
#include "Util/ImageTIF.h"
|
||||
#include "Objects/BaseObject.h"
|
||||
|
||||
#include <IEntityRenderState.h>
|
||||
|
||||
class CubemapSizeModel
|
||||
: public QAbstractListModel
|
||||
{
|
||||
public:
|
||||
CubemapSizeModel(QObject* parent = nullptr)
|
||||
: QAbstractListModel(parent)
|
||||
{ }
|
||||
|
||||
int rowCount(const QModelIndex& parent = {}) const override
|
||||
{
|
||||
return parent.isValid() ? 0 : kNumResolutions;
|
||||
}
|
||||
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
|
||||
{
|
||||
if (!index.isValid() || index.row() >= kNumResolutions)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::UserRole:
|
||||
return 32 << index.row();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kNumResolutions = 6;
|
||||
};
|
||||
|
||||
class CubemapSizeDialog
|
||||
: public QDialog
|
||||
{
|
||||
public:
|
||||
CubemapSizeDialog(QWidget* parent = nullptr)
|
||||
: QDialog(parent)
|
||||
, m_model(new CubemapSizeModel(this))
|
||||
{
|
||||
setWindowTitle(tr("Enter Cubemap Resolution"));
|
||||
|
||||
m_comboBox = new QComboBox;
|
||||
m_comboBox->setModel(m_model);
|
||||
m_comboBox->setCurrentIndex(3);
|
||||
|
||||
auto horLine = new QLabel;
|
||||
horLine->setFrameShape(QFrame::HLine);
|
||||
horLine->setFrameShadow(QFrame::Sunken);
|
||||
|
||||
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->addWidget(m_comboBox);
|
||||
layout->addWidget(horLine);
|
||||
layout->addWidget(buttonBox);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
int GetValue() const
|
||||
{
|
||||
return m_comboBox->currentData().toInt();
|
||||
}
|
||||
|
||||
private:
|
||||
CubemapSizeModel* m_model;
|
||||
QComboBox* m_comboBox;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool CubemapUtils::GenCubemapWithObjectPathAndSize(QString& filename, CBaseObject* pObject, const int size, const bool hideObject)
|
||||
{
|
||||
if (!pObject)
|
||||
{
|
||||
Warning("Select One Entity to Generate Cubemap");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pObject->GetType() != OBJTYPE_AZENTITY)
|
||||
{
|
||||
Warning("Only Entities are allowed as a selected object. Please Select Entity objects");
|
||||
return false;
|
||||
}
|
||||
|
||||
int res = 1;
|
||||
// Make size power of 2.
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (res * 2 > size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
res *= 2;
|
||||
}
|
||||
if (res > 4096)
|
||||
{
|
||||
Warning("Bad texture resolution.\nMust be power of 2 and less or equal to 4096");
|
||||
return false;
|
||||
}
|
||||
|
||||
IRenderNode* pRenderNode = pObject->GetEngineNode();
|
||||
|
||||
// Hide the object before Cubemap generation (maybe). This is useful for when generating a cubemap at an entity's position, like the player,
|
||||
// and you don't want their model showing up in the cubemap. But you want to leave the entity alone if it's a light or something that
|
||||
// has a desired contribution to the cubemap.
|
||||
bool bIsHidden = false;
|
||||
if (pRenderNode)
|
||||
{
|
||||
bIsHidden = (pRenderNode->GetRndFlags() & ERF_HIDDEN) != 0;
|
||||
if (hideObject)
|
||||
{
|
||||
pRenderNode->SetRndFlags(ERF_HIDDEN, true);
|
||||
}
|
||||
}
|
||||
|
||||
QString texname = Path::GetFileName(filename);
|
||||
QString path = Path::GetPath(filename);
|
||||
|
||||
// Add _CM suffix if missing
|
||||
int32 nCMSufixCheck = texname.indexOf("_cm");
|
||||
texname = Path::Make(path, texname + ((nCMSufixCheck == -1) ? "_cm.tif" : ".tif"));
|
||||
|
||||
// Assign this texname to current material.
|
||||
texname = Path::ToUnixPath(texname);
|
||||
|
||||
// Temporary solution to save both dds and tiff hdr cubemap
|
||||
AABB pObjAABB;
|
||||
pObject->GetBoundBox(pObjAABB);
|
||||
|
||||
Vec3 pObjCenter = pObjAABB.GetCenter();
|
||||
|
||||
bool success = GenHDRCubemapTiff(texname, res, pObjCenter);
|
||||
|
||||
// restore object's visibility
|
||||
if (pRenderNode)
|
||||
{
|
||||
pRenderNode->SetRndFlags(ERF_HIDDEN, bIsHidden);
|
||||
}
|
||||
|
||||
filename = Path::ToUnixPath(texname);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CubemapUtils::GenHDRCubemapTiff(const QString& fileName, int nDstSize, Vec3& pos)
|
||||
{
|
||||
int nSrcSize = nDstSize * 4; // Render 16x bigger cubemap (4x4) - 16x SSAA
|
||||
|
||||
TArray<unsigned short> vecData;
|
||||
vecData.Reserve(nSrcSize * nSrcSize * 6 * 4);
|
||||
vecData.SetUse(0);
|
||||
|
||||
if (!GetIEditor()->GetRenderer()->EF_RenderEnvironmentCubeHDR(nSrcSize, pos, vecData))
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(vecData.size() == nSrcSize * nSrcSize * 6 * 4);
|
||||
|
||||
// todo: such big downsampling should be on gpu
|
||||
|
||||
// save data to tiff
|
||||
// resample the image at the original size
|
||||
CWordImage img;
|
||||
img.Allocate(nDstSize * 4 * 6, nDstSize);
|
||||
|
||||
size_t srcPitch = nSrcSize * 4;
|
||||
size_t srcSlideSize = nSrcSize * srcPitch;
|
||||
|
||||
size_t dstPitch = nDstSize * 4;
|
||||
for (int side = 0; side < 6; ++side)
|
||||
{
|
||||
for (uint32 y = 0; y < nDstSize; ++y)
|
||||
{
|
||||
CryHalf4* pSrcSide = (CryHalf4*)&vecData[side * srcSlideSize];
|
||||
CryHalf4* pDst = (CryHalf4*)&img.ValueAt(side * dstPitch, y);
|
||||
for (uint32 x = 0; x < nDstSize; ++x)
|
||||
{
|
||||
Vec4 cResampledColor(0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
// resample the image at the original size
|
||||
for (uint32 yres = 0; yres < 4; ++yres)
|
||||
{
|
||||
for (uint32 xres = 0; xres < 4; ++xres)
|
||||
{
|
||||
const CryHalf4& pSrc = pSrcSide[(y * 4 + yres) * nSrcSize + (x * 4 + xres)];
|
||||
cResampledColor += Vec4(CryConvertHalfToFloat(pSrc.x), CryConvertHalfToFloat(pSrc.y), CryConvertHalfToFloat(pSrc.z), CryConvertHalfToFloat(pSrc.w));
|
||||
}
|
||||
}
|
||||
|
||||
cResampledColor /= 16.f;
|
||||
|
||||
*pDst++ = CryHalf4(cResampledColor.x, cResampledColor.y, cResampledColor.z, cResampledColor.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(CryMemory::IsHeapValid());
|
||||
|
||||
CImageTIF tif;
|
||||
const bool res = tif.SaveRAW(fileName, img.GetData(), nDstSize * 6, nDstSize, 2, 4, true, "HDRCubemap_highQ");
|
||||
assert(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
//function will recurse all probes and generate a cubemap for each
|
||||
void CubemapUtils::RegenerateAllEnvironmentProbeCubemaps()
|
||||
{
|
||||
EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, GenerateAllCubemaps);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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_EDITOR_UTIL_CUBEMAPUTILS_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_CUBEMAPUTILS_H
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace CubemapUtils
|
||||
{
|
||||
//! Generate a cubemap
|
||||
//! \param filename
|
||||
//! \param pObject The cubemap will be generated at this object's location
|
||||
//! \param size Texel dimension of the cubemap
|
||||
//! \param hideObject If true, pObject will be hidden when rendering the cubemap. For example, set this to true if pObject is a model that shouldn't
|
||||
//! show up in the cubemap, or set to false if pObject is a light or probe that should contribute to the cubemap.
|
||||
SANDBOX_API bool GenCubemapWithObjectPathAndSize(QString& filename, CBaseObject* pObject, const int size, const bool hideObject);
|
||||
|
||||
SANDBOX_API bool GenHDRCubemapTiff(const QString& fileName, int size, Vec3& pos);
|
||||
SANDBOX_API void RegenerateAllEnvironmentProbeCubemaps();
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_CUBEMAPUTILS_H
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "Util/ImageGif.h"
|
||||
#include "Util/ImageTIF.h"
|
||||
#include "Util/ImageHDR.h"
|
||||
#include "Util/Image_DXTC.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImageUtil::Save(const QString& strFileName, CImageEx& inImage)
|
||||
@@ -272,10 +271,6 @@ bool CImageUtil::LoadImage(const QString& fileName, CImageEx& image, bool* pQual
|
||||
{
|
||||
return LoadPGM(fileName, image);
|
||||
}
|
||||
else if (azstricmp(ext, ".dds") == 0)
|
||||
{
|
||||
return CImage_DXTC().Load(fileName.toUtf8().data(), image, pQualityLoss);
|
||||
}
|
||||
else if (azstricmp(ext, ".png") == 0)
|
||||
{
|
||||
return CImageUtil::Load(fileName, image);
|
||||
|
||||
@@ -1,806 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "Image_DXTC.h"
|
||||
|
||||
// CryCommon
|
||||
#include <CryCommon/IImage.h>
|
||||
#include <CryCommon/ImageExtensionHelper.h>
|
||||
|
||||
// Editor
|
||||
#include "Util/Image.h"
|
||||
#include "BitFiddling.h"
|
||||
|
||||
|
||||
#ifndef MAKEFOURCC
|
||||
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
|
||||
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
|
||||
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
|
||||
#endif //defined(MAKEFOURCC)
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HDR_UPPERNORM -> factor used when converting from [0,32768] high dynamic range images
|
||||
// to [0,1] low dynamic range images; 32768 = 2^(2^4-1), 4 exponent bits
|
||||
// LDR_UPPERNORM -> factor used when converting from [0,1] low dynamic range images
|
||||
// to 8bit outputs
|
||||
|
||||
#define HDR_UPPERNORM 1.0f // factor set to 1.0, to be able to see content in our rather dark HDR images
|
||||
#define LDR_UPPERNORM 255.0f
|
||||
|
||||
static float GammaToLinear(float x)
|
||||
{
|
||||
return (x <= 0.04045f) ? x / 12.92f : powf((x + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
|
||||
static float LinearToGamma(float x)
|
||||
{
|
||||
return (x <= 0.0031308f) ? x * 12.92f : 1.055f * powf(x, 1.0f / 2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Squish uses non-standard inline friend templates which Recode cannot parse
|
||||
#ifndef __RECODE__
|
||||
AZ_PUSH_DISABLE_WARNING(4819 4828, "-Wunknown-warning-option") // Invalid character not in default code page
|
||||
#include <squish-ccr/squish.h>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
#endif
|
||||
|
||||
// number of bytes per block per type
|
||||
#define BLOCKSIZE_BC1 8
|
||||
#define BLOCKSIZE_BC2 16
|
||||
#define BLOCKSIZE_BC3 16
|
||||
#define BLOCKSIZE_BC4 8
|
||||
#define BLOCKSIZE_BC5 16
|
||||
#define BLOCKSIZE_BC6 16
|
||||
#define BLOCKSIZE_BC7 16
|
||||
|
||||
CImage_DXTC::COMPRESSOR_ERROR CImage_DXTC::DecompressTextureBTC(
|
||||
int width,
|
||||
int height,
|
||||
ETEX_Format sourceFormat,
|
||||
CImage_DXTC::UNCOMPRESSED_FORMAT destinationFormat,
|
||||
[[maybe_unused]] const int imageFlags,
|
||||
const void* sourceData,
|
||||
void* destinationData,
|
||||
int destinationDataSize,
|
||||
int destinationPageOffset)
|
||||
{
|
||||
// Squish uses non-standard inline friend templates which Recode cannot parse
|
||||
#ifndef __RECODE__
|
||||
{
|
||||
const COMPRESSOR_ERROR result = CheckParameters(
|
||||
width,
|
||||
height,
|
||||
destinationFormat,
|
||||
sourceData,
|
||||
destinationData,
|
||||
destinationDataSize);
|
||||
|
||||
if (result != COMPRESSOR_ERROR_NONE)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
int offs = 0;
|
||||
int sourceChannels = 4;
|
||||
switch (sourceFormat)
|
||||
{
|
||||
case eTF_BC1:
|
||||
sourceChannels = 4;
|
||||
flags = squish::kBtc1;
|
||||
break;
|
||||
case eTF_BC2:
|
||||
sourceChannels = 4;
|
||||
flags = squish::kBtc2;
|
||||
break;
|
||||
case eTF_BC3:
|
||||
sourceChannels = 4;
|
||||
flags = squish::kBtc3;
|
||||
break;
|
||||
case eTF_BC4U:
|
||||
sourceChannels = 1;
|
||||
flags = squish::kBtc4;
|
||||
break;
|
||||
case eTF_BC5U:
|
||||
sourceChannels = 2;
|
||||
flags = squish::kBtc5 + squish::kColourMetricUnit;
|
||||
break;
|
||||
case eTF_BC6UH:
|
||||
sourceChannels = 3;
|
||||
flags = squish::kBtc6;
|
||||
break;
|
||||
case eTF_BC7:
|
||||
sourceChannels = 4;
|
||||
flags = squish::kBtc7;
|
||||
break;
|
||||
|
||||
case eTF_BC4S:
|
||||
sourceChannels = 1;
|
||||
flags = squish::kBtc4 + squish::kSignedInternal + squish::kSignedExternal;
|
||||
offs = 0x80;
|
||||
break;
|
||||
case eTF_BC5S:
|
||||
sourceChannels = 2;
|
||||
flags = squish::kBtc5 + squish::kSignedInternal + squish::kSignedExternal + squish::kColourMetricUnit;
|
||||
offs = 0x80;
|
||||
break;
|
||||
case eTF_BC6SH:
|
||||
sourceChannels = 3;
|
||||
flags = squish::kBtc6 + squish::kSignedInternal + squish::kSignedExternal;
|
||||
offs = 0x80;
|
||||
break;
|
||||
|
||||
default:
|
||||
return COMPRESSOR_ERROR_UNSUPPORTED_SOURCE_FORMAT;
|
||||
}
|
||||
|
||||
squish::sqio::dtp datatype = !IsLimitedHDR(sourceFormat) ? squish::sqio::dtp::DT_U8 : squish::sqio::dtp::DT_F23;
|
||||
switch (destinationFormat)
|
||||
{
|
||||
case FORMAT_ARGB_8888: /*datatype = squish::sqio::dtp::DT_U8;*/
|
||||
break;
|
||||
// case FORMAT_ARGB_16161616: datatype = squish::sqio::dtp::DT_U16; break;
|
||||
// case FORMAT_ARGB_32323232F: datatype = squish::sqio::dtp::DT_F23; break;
|
||||
default:
|
||||
return COMPRESSOR_ERROR_UNSUPPORTED_DESTINATION_FORMAT;
|
||||
}
|
||||
|
||||
struct squish::sqio sqio = squish::GetSquishIO(width, height, datatype, flags);
|
||||
|
||||
const int blockChannels = 4;
|
||||
const int blockWidth = 4;
|
||||
const int blockHeight = 4;
|
||||
|
||||
const int pixelStride = blockChannels * sizeof(uint8);
|
||||
const int rowStride = (destinationPageOffset ? destinationPageOffset : pixelStride * width);
|
||||
|
||||
if ((datatype == squish::sqio::dtp::DT_U8) && (destinationFormat == FORMAT_ARGB_8888))
|
||||
{
|
||||
const char* src = (const char*)sourceData;
|
||||
for (int y = 0; y < height; y += blockHeight)
|
||||
{
|
||||
uint8* dst = ((uint8*)destinationData) + (y * rowStride);
|
||||
|
||||
for (int x = 0; x < width; x += blockWidth)
|
||||
{
|
||||
uint8 values[blockHeight][blockWidth][blockChannels] = { { { 0 } } };
|
||||
|
||||
// decode
|
||||
sqio.decoder((uint8*)values, src, sqio.flags);
|
||||
|
||||
// transfer
|
||||
for (int by = 0; by < blockHeight; by += 1)
|
||||
{
|
||||
uint8* bdst = ((uint8*)dst) + (by * rowStride);
|
||||
|
||||
for (int bx = 0; bx < blockWidth; bx += 1)
|
||||
{
|
||||
bdst[bx * pixelStride + 0] = sourceChannels <= 0 ? 0U : (values[by][bx][0] + offs);
|
||||
bdst[bx * pixelStride + 1] = sourceChannels <= 1 ? bdst[bx * pixelStride + 0] : (values[by][bx][1] + offs);
|
||||
bdst[bx * pixelStride + 2] = sourceChannels <= 1 ? bdst[bx * pixelStride + 0] : (values[by][bx][2] + offs);
|
||||
bdst[bx * pixelStride + 3] = sourceChannels <= 3 ? 255U : (values[by][bx][3]);
|
||||
}
|
||||
}
|
||||
|
||||
dst += blockWidth * pixelStride;
|
||||
src += sqio.blocksize;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((datatype == squish::sqio::dtp::DT_F23) && (destinationFormat == FORMAT_ARGB_8888))
|
||||
{
|
||||
const char* src = (const char*)sourceData;
|
||||
for (int y = 0; y < height; y += blockHeight)
|
||||
{
|
||||
uint8* dst = ((uint8*)destinationData) + (y * rowStride);
|
||||
|
||||
for (int x = 0; x < width; x += blockWidth)
|
||||
{
|
||||
float values[blockHeight][blockWidth][blockChannels] = { { { 0 } } };
|
||||
|
||||
// decode
|
||||
sqio.decoder((float*)values, src, sqio.flags);
|
||||
|
||||
// transfer
|
||||
for (int by = 0; by < blockHeight; by += 1)
|
||||
{
|
||||
uint8* bdst = ((uint8*)dst) + (by * rowStride);
|
||||
|
||||
for (int bx = 0; bx < blockWidth; bx += 1)
|
||||
{
|
||||
bdst[bx * pixelStride + 0] = sourceChannels <= 0 ? 0U : std::min((uint8)255, (uint8)floorf(values[by][bx][0] * LDR_UPPERNORM / HDR_UPPERNORM + 0.5f));
|
||||
bdst[bx * pixelStride + 1] = sourceChannels <= 1 ? bdst[bx * pixelStride + 0] : std::min((uint8)255, (uint8)floorf(values[by][bx][1] * LDR_UPPERNORM / HDR_UPPERNORM + 0.5f));
|
||||
bdst[bx * pixelStride + 2] = sourceChannels <= 1 ? bdst[bx * pixelStride + 0] : std::min((uint8)255, (uint8)floorf(values[by][bx][2] * LDR_UPPERNORM / HDR_UPPERNORM + 0.5f));
|
||||
bdst[bx * pixelStride + 3] = sourceChannels <= 3 ? 255U : 255U;
|
||||
}
|
||||
}
|
||||
|
||||
dst += blockWidth * pixelStride;
|
||||
src += sqio.blocksize;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return COMPRESSOR_ERROR_NONE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CImage_DXTC::CImage_DXTC()
|
||||
{
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CImage_DXTC::~CImage_DXTC()
|
||||
{
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImage_DXTC::Load(const char* filename, CImageEx& outImage, bool* pQualityLoss)
|
||||
{
|
||||
if (pQualityLoss)
|
||||
{
|
||||
*pQualityLoss = false;
|
||||
}
|
||||
|
||||
_smart_ptr<IImageFile> pImage = gEnv->pRenderer->EF_LoadImage(filename, 0);
|
||||
|
||||
if (!pImage)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
BYTE* pDecompBytes;
|
||||
|
||||
ETEX_Format eFormat = pImage->mfGetFormat();
|
||||
int imageFlags = pImage->mfGet_Flags();
|
||||
|
||||
if (eFormat == eTF_Unknown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_smart_ptr<IImageFile> pAlphaImage;
|
||||
|
||||
ETEX_Format eAttachedFormat = eTF_Unknown;
|
||||
|
||||
if (imageFlags & FIM_HAS_ATTACHED_ALPHA)
|
||||
{
|
||||
if (pAlphaImage = gEnv->pRenderer->EF_LoadImage(filename, FIM_ALPHA))
|
||||
{
|
||||
eAttachedFormat = pAlphaImage->mfGetFormat();
|
||||
}
|
||||
}
|
||||
|
||||
const bool bIsSRGB = (imageFlags & FIM_SRGB_READ) != 0;
|
||||
outImage.SetSRGB(bIsSRGB);
|
||||
|
||||
const uint32 imageWidth = pImage->mfGet_width();
|
||||
const uint32 imageHeight = pImage->mfGet_height();
|
||||
const uint32 numMips = pImage->mfGet_numMips();
|
||||
|
||||
int nHorizontalFaces(1);
|
||||
int nVerticalFaces(1);
|
||||
int nTargetPitch(imageWidth * 4);
|
||||
int nTargetPageSize(nTargetPitch * imageHeight);
|
||||
|
||||
int nHorizontalPageOffset(nTargetPitch);
|
||||
int nVerticalPageOffset(0);
|
||||
bool boIsCubemap = pImage->mfGet_NumSides() == 6;
|
||||
if (boIsCubemap)
|
||||
{
|
||||
nHorizontalFaces = 3;
|
||||
nVerticalFaces = 2;
|
||||
nHorizontalPageOffset = nTargetPitch * nHorizontalFaces;
|
||||
nVerticalPageOffset = nTargetPageSize * nHorizontalFaces;
|
||||
}
|
||||
|
||||
outImage.Allocate(imageWidth * nHorizontalFaces, imageHeight * nVerticalFaces);
|
||||
pDecompBytes = (BYTE*)outImage.GetData();
|
||||
if (!pDecompBytes)
|
||||
{
|
||||
Warning("Cannot allocate image %dx%d, Out of memory", imageWidth, imageHeight);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pQualityLoss)
|
||||
{
|
||||
*pQualityLoss = CImageExtensionHelper::IsQuantized(eFormat);
|
||||
}
|
||||
|
||||
bool bOk = true;
|
||||
|
||||
int nCurrentFace(0);
|
||||
int nCurrentHorizontalFace(0);
|
||||
int nCurrentVerticalFace(0);
|
||||
unsigned char* dest(NULL);
|
||||
const unsigned char* src(NULL);
|
||||
|
||||
unsigned char* basedest(NULL);
|
||||
const unsigned char* basesrc(NULL);
|
||||
|
||||
for (nCurrentHorizontalFace = 0; nCurrentHorizontalFace < nHorizontalFaces; ++nCurrentHorizontalFace)
|
||||
{
|
||||
basedest = &pDecompBytes[nTargetPitch * nCurrentHorizontalFace]; // Horizontal offset.
|
||||
for (nCurrentVerticalFace = 0; nCurrentVerticalFace < nVerticalFaces; ++nCurrentVerticalFace, ++nCurrentFace)
|
||||
{
|
||||
basedest += nVerticalPageOffset * nCurrentVerticalFace; // Vertical offset.
|
||||
|
||||
basesrc = src = pImage->mfGet_image(nCurrentFace);
|
||||
|
||||
if (eFormat == eTF_R8G8B8A8 || eFormat == eTF_R8G8B8A8S)
|
||||
{
|
||||
for (int y = 0; y < imageHeight; y++)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; x++)
|
||||
{
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = src[3];
|
||||
|
||||
dest += 4;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (eFormat == eTF_B8G8R8A8)
|
||||
{
|
||||
for (int y = 0; y < imageHeight; y++)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; x++)
|
||||
{
|
||||
dest[0] = src[2];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[0];
|
||||
dest[3] = src[3];
|
||||
|
||||
dest += 4;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (eFormat == eTF_B8G8R8X8)
|
||||
{
|
||||
for (int y = 0; y < imageHeight; y++)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; x++)
|
||||
{
|
||||
dest[0] = src[2];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[0];
|
||||
dest[3] = 255;
|
||||
|
||||
dest += 4;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (eFormat == eTF_B8G8R8)
|
||||
{
|
||||
for (int y = 0; y < imageHeight; y++)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; x++)
|
||||
{
|
||||
dest[0] = src[2];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[0];
|
||||
dest[3] = 255;
|
||||
|
||||
dest += 4;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (eFormat == eTF_L8)
|
||||
{
|
||||
for (int y = 0; y < imageHeight; y++)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; x++)
|
||||
{
|
||||
dest[0] = *src;
|
||||
dest[1] = *src;
|
||||
dest[2] = *src;
|
||||
dest[3] = 255;
|
||||
|
||||
dest += 4;
|
||||
src += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (eFormat == eTF_A8)
|
||||
{
|
||||
for (int y = 0; y < imageHeight; y++)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; x++)
|
||||
{
|
||||
dest[0] = 0;
|
||||
dest[1] = 0;
|
||||
dest[2] = 0;
|
||||
dest[3] = *src;
|
||||
|
||||
dest += 4;
|
||||
src += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (eFormat == eTF_A8L8)
|
||||
{
|
||||
for (int y = 0; y < imageHeight; y++)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; x++)
|
||||
{
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[0];
|
||||
dest[2] = src[0];
|
||||
dest[3] = src[1];
|
||||
|
||||
dest += 4;
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (eFormat == eTF_R9G9B9E5)
|
||||
{
|
||||
const int nSourcePitch = imageWidth * 4;
|
||||
|
||||
for (int y = 0; y < imageHeight; y++)
|
||||
{
|
||||
src = basesrc + nSourcePitch * y; //Scanline position.
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; x++)
|
||||
{
|
||||
const struct RgbE
|
||||
{
|
||||
unsigned int r : 9, g : 9, b : 9, e : 5;
|
||||
}* srcv = (const struct RgbE*)src;
|
||||
|
||||
const float escale = powf(2.0f, int(srcv->e) - 15 - 9) * LDR_UPPERNORM / HDR_UPPERNORM;
|
||||
|
||||
dest[0] = std::min((uint8)255, (uint8)floorf(srcv->r * escale + 0.5f));
|
||||
dest[1] = std::min((uint8)255, (uint8)floorf(srcv->g * escale + 0.5f));
|
||||
dest[2] = std::min((uint8)255, (uint8)floorf(srcv->b * escale + 0.5f));
|
||||
dest[3] = 255U;
|
||||
|
||||
dest += 4;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const int pixelCount = imageWidth * imageHeight;
|
||||
const int outputBufferSize = pixelCount * 4;
|
||||
const int mipCount = numMips;
|
||||
|
||||
const COMPRESSOR_ERROR err = DecompressTextureBTC(imageWidth, imageHeight, eFormat, FORMAT_ARGB_8888, imageFlags, basesrc, basedest, outputBufferSize, nHorizontalPageOffset);
|
||||
if (err != COMPRESSOR_ERROR_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// alpha channel might be attached
|
||||
if (imageFlags & FIM_HAS_ATTACHED_ALPHA)
|
||||
{
|
||||
if (IsBlockCompressed(eAttachedFormat))
|
||||
{
|
||||
const byte* const basealpha = pAlphaImage->mfGet_image(0);
|
||||
const int alphaImageWidth = pAlphaImage->mfGet_width();
|
||||
const int alphaImageHeight = pAlphaImage->mfGet_height();
|
||||
const int alphaImageFlags = pAlphaImage->mfGet_Flags();
|
||||
const int tmpOutputBufferSize = imageWidth * imageHeight * 4;
|
||||
uint8* tmpOutputBuffer = new uint8[tmpOutputBufferSize];
|
||||
|
||||
const COMPRESSOR_ERROR err = DecompressTextureBTC(alphaImageWidth, alphaImageHeight, eAttachedFormat, FORMAT_ARGB_8888, alphaImageFlags, basealpha, tmpOutputBuffer, tmpOutputBufferSize, 0);
|
||||
if (err != COMPRESSOR_ERROR_NONE)
|
||||
{
|
||||
delete []tmpOutputBuffer;
|
||||
return false;
|
||||
}
|
||||
|
||||
// assuming attached image can have lower res and difference is power of two
|
||||
const uint32 reducex = IntegerLog2((uint32)(imageWidth / alphaImageWidth));
|
||||
const uint32 reducey = IntegerLog2((uint32)(imageHeight / alphaImageHeight));
|
||||
|
||||
for (int y = 0; y < imageHeight; ++y)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; ++x)
|
||||
{
|
||||
dest[3] = tmpOutputBuffer[((x >> reducex) + (y >> reducey) * alphaImageWidth) * 4];
|
||||
dest += 4;
|
||||
}
|
||||
}
|
||||
|
||||
delete []tmpOutputBuffer;
|
||||
}
|
||||
else if (eAttachedFormat != eTF_Unknown)
|
||||
{
|
||||
const byte* const basealpha = pAlphaImage->mfGet_image(0); // assuming it's A8 format (ensured with assets when loading)
|
||||
const int alphaImageWidth = pAlphaImage->mfGet_width();
|
||||
const int alphaImageHeight = pAlphaImage->mfGet_height();
|
||||
const int alphaImageFlags = pAlphaImage->mfGet_Flags();
|
||||
|
||||
// assuming attached image can have lower res and difference is power of two
|
||||
const uint32 reducex = IntegerLog2((uint32)(imageWidth / alphaImageWidth));
|
||||
const uint32 reducey = IntegerLog2((uint32)(imageHeight / alphaImageHeight));
|
||||
|
||||
for (int y = 0; y < imageHeight; ++y)
|
||||
{
|
||||
dest = basedest + nHorizontalPageOffset * y; // Pixel position.
|
||||
|
||||
for (int x = 0; x < imageWidth; ++x)
|
||||
{
|
||||
dest[3] = basealpha[(x >> reducex) + (y >> reducey) * alphaImageWidth];
|
||||
dest += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// destination range is 8bits
|
||||
// rescale in linear space
|
||||
float cScaleR = 1.0f;
|
||||
float cScaleG = 1.0f;
|
||||
float cScaleB = 1.0f;
|
||||
float cScaleA = 1.0f;
|
||||
float cLowR = 0.0f;
|
||||
float cLowG = 0.0f;
|
||||
float cLowB = 0.0f;
|
||||
float cLowA = 0.0f;
|
||||
|
||||
if (imageFlags & FIM_RENORMALIZED_TEXTURE)
|
||||
{
|
||||
const ColorF cMinColor = pImage->mfGet_minColor();
|
||||
const ColorF cMaxColor = pImage->mfGet_maxColor();
|
||||
|
||||
// base range after normalization, fe. [0,1] for 8bit images, or [0,2^15] for RGBE/HDR data
|
||||
float cUprValue = 1.0f;
|
||||
if ((eFormat == eTF_R9G9B9E5) || (eFormat == eTF_BC6UH) || (eFormat == eTF_BC6SH))
|
||||
{
|
||||
cUprValue = cMaxColor.a / HDR_UPPERNORM;
|
||||
}
|
||||
|
||||
// original range before normalization, fe. [0,1.83567]
|
||||
cScaleR = (cMaxColor.r - cMinColor.r) / cUprValue;
|
||||
cScaleG = (cMaxColor.g - cMinColor.g) / cUprValue;
|
||||
cScaleB = (cMaxColor.b - cMinColor.b) / cUprValue;
|
||||
// original offset before normalization, fe. [0.0001204]
|
||||
cLowR = cMinColor.r;
|
||||
cLowG = cMinColor.g;
|
||||
cLowB = cMinColor.b;
|
||||
}
|
||||
|
||||
if (imageFlags & FIM_HAS_ATTACHED_ALPHA)
|
||||
{
|
||||
if (pAlphaImage)
|
||||
{
|
||||
const int alphaImageFlags = pAlphaImage->mfGet_Flags();
|
||||
|
||||
if (alphaImageFlags & FIM_RENORMALIZED_TEXTURE)
|
||||
{
|
||||
const ColorF cMinColor = pAlphaImage->mfGet_minColor();
|
||||
const ColorF cMaxColor = pAlphaImage->mfGet_maxColor();
|
||||
|
||||
// base range after normalization, fe. [0,1] for 8bit images, or [0,2^15] for RGBE/HDR data
|
||||
float cUprValue = 1.0f;
|
||||
if ((eFormat == eTF_R9G9B9E5) || (eFormat == eTF_BC6UH) || (eFormat == eTF_BC6SH))
|
||||
{
|
||||
cUprValue = cMaxColor.a / HDR_UPPERNORM;
|
||||
}
|
||||
|
||||
// original range before normalization, fe. [0,1.83567]
|
||||
cScaleA = (cMaxColor.r - cMinColor.r) / cUprValue;
|
||||
// original offset before normalization, fe. [0.0001204]
|
||||
cLowA = cMinColor.r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cScaleR != 1.0f || cScaleG != 1.0f || cScaleB != 1.0f || cScaleA != 1.0f ||
|
||||
cLowR != 0.0f || cLowG != 0.0f || cLowB != 0.0f || cLowA != 0.0f)
|
||||
{
|
||||
if ((eFormat == eTF_R9G9B9E5) || (eFormat == eTF_BC6UH) || (eFormat == eTF_BC6SH))
|
||||
{
|
||||
imageFlags &= ~FIM_SRGB_READ;
|
||||
}
|
||||
|
||||
if (imageFlags & FIM_SRGB_READ)
|
||||
{
|
||||
for (int s = 0; s < (imageWidth * nHorizontalFaces * imageHeight * nVerticalFaces * 4); s += 4)
|
||||
{
|
||||
pDecompBytes[s + 0] = std::min((uint8)255, uint8(LinearToGamma(GammaToLinear(pDecompBytes[s + 0] / LDR_UPPERNORM) * cScaleR + cLowR) * LDR_UPPERNORM + 0.5f));
|
||||
pDecompBytes[s + 1] = std::min((uint8)255, uint8(LinearToGamma(GammaToLinear(pDecompBytes[s + 1] / LDR_UPPERNORM) * cScaleG + cLowG) * LDR_UPPERNORM + 0.5f));
|
||||
pDecompBytes[s + 2] = std::min((uint8)255, uint8(LinearToGamma(GammaToLinear(pDecompBytes[s + 2] / LDR_UPPERNORM) * cScaleB + cLowB) * LDR_UPPERNORM + 0.5f));
|
||||
pDecompBytes[s + 3] = std::min((uint8)255, uint8(LinearToGamma(GammaToLinear(pDecompBytes[s + 3] / LDR_UPPERNORM) * cScaleA + cLowA) * LDR_UPPERNORM + 0.5f));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int s = 0; s < (imageWidth * nHorizontalFaces * imageHeight * nVerticalFaces * 4); s += 4)
|
||||
{
|
||||
pDecompBytes[s + 0] = std::min((uint8)255, uint8(pDecompBytes[s + 0] * cScaleR + cLowR * LDR_UPPERNORM + 0.5f));
|
||||
pDecompBytes[s + 1] = std::min((uint8)255, uint8(pDecompBytes[s + 1] * cScaleG + cLowG * LDR_UPPERNORM + 0.5f));
|
||||
pDecompBytes[s + 2] = std::min((uint8)255, uint8(pDecompBytes[s + 2] * cScaleB + cLowB * LDR_UPPERNORM + 0.5f));
|
||||
pDecompBytes[s + 3] = std::min((uint8)255, uint8(pDecompBytes[s + 3] * cScaleA + cLowA * LDR_UPPERNORM + 0.5f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool hasAlpha = (eAttachedFormat != eTF_Unknown) /*|| CImageExtensionHelper::HasAlphaForTextureFormat(eFormat)*/;
|
||||
for (int s = 0; s < (imageWidth * nHorizontalFaces * imageHeight * nVerticalFaces); s += 4)
|
||||
{
|
||||
hasAlpha |= (pDecompBytes[s + 3] != 0xFF);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString strFormat = NameForTextureFormat(eFormat);
|
||||
QString mips;
|
||||
mips = QStringLiteral(" Mips:%1").arg(numMips);
|
||||
|
||||
if (eAttachedFormat != eTF_Unknown)
|
||||
{
|
||||
strFormat += " + ";
|
||||
strFormat += NameForTextureFormat(eAttachedFormat);
|
||||
}
|
||||
|
||||
strFormat += mips;
|
||||
|
||||
// Check whether it's gamma-corrected or not and add a description accordingly.
|
||||
if (imageFlags & FIM_SRGB_READ)
|
||||
{
|
||||
strFormat += ", SRGB/Gamma corrected";
|
||||
}
|
||||
if (imageFlags & FIM_RENORMALIZED_TEXTURE)
|
||||
{
|
||||
strFormat += ", Renormalized";
|
||||
}
|
||||
if (IsLimitedHDR(eFormat))
|
||||
{
|
||||
strFormat += ", HDR";
|
||||
}
|
||||
|
||||
outImage.SetFormatDescription(strFormat);
|
||||
outImage.SetNumberOfMipMaps(numMips);
|
||||
outImage.SetHasAlphaChannel(hasAlpha);
|
||||
outImage.SetIsLimitedHDR(IsLimitedHDR(eFormat));
|
||||
outImage.SetIsCubemap(boIsCubemap);
|
||||
outImage.SetFormat(eFormat);
|
||||
outImage.SetSRGB(imageFlags & FIM_SRGB_READ);
|
||||
|
||||
// done reading file
|
||||
return bOk;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CImage_DXTC::TextureDataSize(int nWidth, int nHeight, int nDepth, int nMips, ETEX_Format eTF)
|
||||
{
|
||||
if (eTF == eTF_Unknown)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nMips <= 0)
|
||||
{
|
||||
nMips = 0;
|
||||
}
|
||||
int nSize = 0;
|
||||
int nM = 0;
|
||||
while (nWidth || nHeight || nDepth)
|
||||
{
|
||||
if (!nWidth)
|
||||
{
|
||||
nWidth = 1;
|
||||
}
|
||||
if (!nHeight)
|
||||
{
|
||||
nHeight = 1;
|
||||
}
|
||||
if (!nDepth)
|
||||
{
|
||||
nDepth = 1;
|
||||
}
|
||||
nM++;
|
||||
|
||||
int nSingleMipSize;
|
||||
if (IsBlockCompressed(eTF))
|
||||
{
|
||||
int blockSize = CImageExtensionHelper::BytesPerBlock(eTF);
|
||||
const Vec2i blockDim = CImageExtensionHelper::GetBlockDim(eTF);
|
||||
nSingleMipSize = ((nWidth + blockDim.x - 1) / blockDim.x) * ((nHeight + blockDim.y - 1) / blockDim.y) * nDepth * blockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSingleMipSize = nWidth * nHeight * nDepth * CImageExtensionHelper::BytesPerBlock(eTF);
|
||||
}
|
||||
nSize += nSingleMipSize;
|
||||
|
||||
nWidth >>= 1;
|
||||
nHeight >>= 1;
|
||||
nDepth >>= 1;
|
||||
if (nMips == nM)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
//assert (nM == nMips);
|
||||
|
||||
return nSize;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CImage_DXTC::COMPRESSOR_ERROR CImage_DXTC::CheckParameters(
|
||||
int width,
|
||||
int height,
|
||||
CImage_DXTC::UNCOMPRESSED_FORMAT destinationFormat,
|
||||
const void* sourceData,
|
||||
void* destinationData,
|
||||
int destinationDataSize)
|
||||
{
|
||||
const int blockWidth = 4;
|
||||
const int blockHeight = 4;
|
||||
|
||||
const int bgraPixelSize = 4 * sizeof(uint8);
|
||||
const int bgraRowSize = bgraPixelSize * width;
|
||||
|
||||
if ((width <= 0) || (height <= 0) || (!sourceData))
|
||||
{
|
||||
return COMPRESSOR_ERROR_NO_INPUT_DATA;
|
||||
}
|
||||
|
||||
if ((width % blockWidth) || (height % blockHeight))
|
||||
{
|
||||
return COMPRESSOR_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
if ((destinationData == 0) || (destinationDataSize <= 0))
|
||||
{
|
||||
return COMPRESSOR_ERROR_NO_OUTPUT_POINTER;
|
||||
}
|
||||
|
||||
if (destinationFormat != FORMAT_ARGB_8888)
|
||||
{
|
||||
return COMPRESSOR_ERROR_UNSUPPORTED_DESTINATION_FORMAT;
|
||||
}
|
||||
|
||||
if ((height * bgraRowSize <= 0) || (height * bgraRowSize > destinationDataSize))
|
||||
{
|
||||
return COMPRESSOR_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
return COMPRESSOR_ERROR_NONE;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* 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_EDITOR_UTIL_IMAGE_DXTC_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_IMAGE_DXTC_H
|
||||
#pragma once
|
||||
|
||||
#include "ImageExtensionHelper.h"
|
||||
|
||||
class CImageEx;
|
||||
|
||||
class CImage_DXTC
|
||||
{
|
||||
// Typedefs
|
||||
public:
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Extracted from Compressorlib.h on SDKs\CompressATI directory.
|
||||
// Added here because we are not really using the elements inside
|
||||
// this header file apart from those definitions as we are currently
|
||||
// loading the DLL CompressATI2.dll manually as recommended by the rendering
|
||||
// team.
|
||||
typedef enum
|
||||
{
|
||||
FORMAT_ARGB_8888,
|
||||
FORMAT_ARGB_TOOBIG
|
||||
} UNCOMPRESSED_FORMAT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
COMPRESSOR_ERROR_NONE,
|
||||
COMPRESSOR_ERROR_NO_INPUT_DATA,
|
||||
COMPRESSOR_ERROR_NO_OUTPUT_POINTER,
|
||||
COMPRESSOR_ERROR_UNSUPPORTED_SOURCE_FORMAT,
|
||||
COMPRESSOR_ERROR_UNSUPPORTED_DESTINATION_FORMAT,
|
||||
COMPRESSOR_ERROR_UNABLE_TO_INIT_CODEC,
|
||||
COMPRESSOR_ERROR_GENERIC
|
||||
} COMPRESSOR_ERROR;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Methods
|
||||
public:
|
||||
CImage_DXTC();
|
||||
~CImage_DXTC();
|
||||
|
||||
// Arguments:
|
||||
// pQualityLoss - 0 if info is not needed, pointer to the result otherwise - not need to preinitialize
|
||||
bool Load(const char* filename, CImageEx& outImage, bool* pQualityLoss = 0); // true if success
|
||||
|
||||
static inline const char* NameForTextureFormat(ETEX_Format ETF) { return CImageExtensionHelper::NameForTextureFormat(ETF); }
|
||||
static inline bool IsBlockCompressed(ETEX_Format ETF) { return CImageExtensionHelper::IsBlockCompressed(ETF); }
|
||||
static inline bool IsLimitedHDR(ETEX_Format ETF) { return CImageExtensionHelper::IsRangeless(ETF); }
|
||||
|
||||
int TextureDataSize(int nWidth, int nHeight, int nDepth, int nMips, ETEX_Format eTF);
|
||||
|
||||
private:
|
||||
static COMPRESSOR_ERROR CheckParameters(
|
||||
int width,
|
||||
int height,
|
||||
UNCOMPRESSED_FORMAT destinationFormat,
|
||||
const void* sourceData,
|
||||
void* destinationData,
|
||||
int destinationDataSize);
|
||||
|
||||
static COMPRESSOR_ERROR DecompressTextureBTC(
|
||||
int width,
|
||||
int height,
|
||||
ETEX_Format sourceFormat,
|
||||
UNCOMPRESSED_FORMAT destinationFormat,
|
||||
const int imageFlags,
|
||||
const void* sourceData,
|
||||
void* destinationData,
|
||||
int destinationDataSize,
|
||||
int destinationPageOffset);
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_IMAGE_DXTC_H
|
||||
@@ -1,268 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Ruler helper for Editor to determine distances
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "Ruler.h"
|
||||
|
||||
// Editor
|
||||
#include "Settings.h"
|
||||
#include "Viewport.h"
|
||||
#include "Include/HitContext.h"
|
||||
#include "Include/IObjectManager.h"
|
||||
#include "Objects/BaseObject.h"
|
||||
|
||||
// Qt
|
||||
#include <QtGui/private/qhighdpiscaling_p.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CRuler::CRuler()
|
||||
: m_bActive(false)
|
||||
, m_MouseOverObject(GUID_NULL)
|
||||
, m_sphereScale(0.5f)
|
||||
, m_sphereTrans(0.5f)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CRuler::~CRuler()
|
||||
{
|
||||
SetActive(false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CRuler::HasQueuedPaths() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRuler::SetActive(bool bActive)
|
||||
{
|
||||
if (m_bActive != bActive)
|
||||
{
|
||||
m_bActive = bActive;
|
||||
|
||||
if (m_bActive)
|
||||
{
|
||||
m_sphereScale = gSettings.gizmo.rulerSphereScale;
|
||||
m_sphereTrans = gSettings.gizmo.rulerSphereTrans;
|
||||
}
|
||||
|
||||
// Reset
|
||||
m_startPoint.Reset();
|
||||
m_endPoint.Reset();
|
||||
|
||||
CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(m_MouseOverObject);
|
||||
if (pObject)
|
||||
{
|
||||
pObject->SetHighlight(false);
|
||||
}
|
||||
m_MouseOverObject = GUID_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRuler::Update()
|
||||
{
|
||||
if (!IsActive())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckVirtualKey(Qt::Key_Escape))
|
||||
{
|
||||
SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
static const ColorF colours[] =
|
||||
{
|
||||
Col_Blue,
|
||||
Col_Green,
|
||||
Col_Red,
|
||||
Col_Yellow,
|
||||
Col_Magenta,
|
||||
Col_Black,
|
||||
};
|
||||
|
||||
IRenderer* pRenderer = GetIEditor()->GetSystem()->GetIRenderer();
|
||||
CRY_ASSERT(pRenderer);
|
||||
IRenderAuxGeom* pAuxGeom = pRenderer->GetIRenderAuxGeom();
|
||||
CRY_ASSERT(pAuxGeom);
|
||||
|
||||
CViewport* pActiveView = GetIEditor()->GetActiveView();
|
||||
if (pActiveView)
|
||||
{
|
||||
// Draw where cursor currently is
|
||||
if (!IsObjectSelectMode(pActiveView))
|
||||
{
|
||||
QPoint vCursorPoint = QCursor::pos();
|
||||
pActiveView->ScreenToClient(vCursorPoint);
|
||||
vCursorPoint = QHighDpi::toNativePixels(vCursorPoint, QGuiApplication::screenAt(vCursorPoint));
|
||||
Vec3 vCursorWorldPos = pActiveView->SnapToGrid(pActiveView->ViewToWorld(vCursorPoint));
|
||||
Vec3 vOffset(0.1f, 0.1f, 0.1f);
|
||||
pAuxGeom->SetRenderFlags(e_Def3DPublicRenderflags | e_AlphaBlended);
|
||||
pAuxGeom->DrawSphere(vCursorWorldPos, m_sphereScale, ColorF(0.5, 0.5, 0.5, m_sphereTrans));
|
||||
pAuxGeom->DrawAABB(AABB(vCursorWorldPos - vOffset * m_sphereScale, vCursorWorldPos + vOffset * m_sphereScale), false, ColorF(1.0f, 0.0f, 0.0f, 1.0f), eBBD_Faceted);
|
||||
}
|
||||
|
||||
uint32 x = 12, y = 60;
|
||||
|
||||
if (!m_startPoint.IsEmpty())
|
||||
{
|
||||
//pAuxGeom->DrawSphere(m_startPoint.GetPos(), 1.0f, ColorB(255,255,255,255));
|
||||
m_startPoint.Render(pRenderer);
|
||||
}
|
||||
if (!m_endPoint.IsEmpty())
|
||||
{
|
||||
//pAuxGeom->DrawSphere(m_endPoint.GetPos(), 1.0f, ColorB(255,255,255,255));
|
||||
m_endPoint.Render(pRenderer);
|
||||
|
||||
pAuxGeom->DrawLine(m_startPoint.GetPos(), ColorB(255, 255, 255, 255), m_endPoint.GetPos(), ColorB(255, 255, 255, 255));
|
||||
|
||||
string sTempText;
|
||||
|
||||
// Compute distance and output results
|
||||
// TODO: Consider movement speed outputs here as well?
|
||||
const float fDistance = m_startPoint.GetDistance(m_endPoint);
|
||||
sTempText.Format("Straight-line distance: %.3f", fDistance);
|
||||
|
||||
// Draw mid text
|
||||
float white[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
pRenderer->Draw2dLabel(x, y, 2.0f, white, false, sTempText.c_str());
|
||||
y += 18;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CRuler::IsObjectSelectMode([[maybe_unused]] CViewport* pView) const
|
||||
{
|
||||
const bool bShiftDown = CheckVirtualKey(Qt::Key_Shift);
|
||||
|
||||
return (bShiftDown);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRuler::UpdateRulerPoint(CViewport* pView, const QPoint& point, CRulerPoint& rulerPoint, bool bRequestPath)
|
||||
{
|
||||
CRY_ASSERT(pView);
|
||||
|
||||
const bool bObjectSelect = IsObjectSelectMode(pView);
|
||||
|
||||
rulerPoint.SetHelperSettings(m_sphereScale, m_sphereTrans);
|
||||
|
||||
// Do entity hit check
|
||||
if (bObjectSelect)
|
||||
{
|
||||
HitContext hitInfo;
|
||||
pView->HitTest(point, hitInfo);
|
||||
|
||||
CBaseObject* pHitObj = hitInfo.object;
|
||||
rulerPoint.Set(pHitObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3 vWorldPoint = pView->SnapToGrid(pView->ViewToWorld(point));
|
||||
rulerPoint.Set(vWorldPoint);
|
||||
}
|
||||
|
||||
if (bRequestPath)
|
||||
{
|
||||
RequestPath();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRuler::RequestPath()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CRuler::MouseCallback(CViewport* pView, EMouseEvent event, QPoint& point, int flags)
|
||||
{
|
||||
bool bResult = IsActive();
|
||||
|
||||
if (bResult)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case eMouseMove:
|
||||
OnMouseMove(pView, point, flags);
|
||||
break;
|
||||
case eMouseLUp:
|
||||
OnLButtonUp(pView, point, flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRuler::OnMouseMove(CViewport* pView, QPoint& point, [[maybe_unused]] int flags)
|
||||
{
|
||||
GUID hitGUID = GUID_NULL;
|
||||
|
||||
if (IsObjectSelectMode(pView))
|
||||
{
|
||||
// Check for hit entity
|
||||
HitContext hitInfo;
|
||||
pView->HitTest(point, hitInfo);
|
||||
CBaseObject* pHitObj = hitInfo.object;
|
||||
if (pHitObj)
|
||||
{
|
||||
hitGUID = pHitObj->GetId();
|
||||
}
|
||||
}
|
||||
|
||||
if (hitGUID != m_MouseOverObject)
|
||||
{
|
||||
// Kill highlight on old
|
||||
CBaseObject* pOldObj = GetIEditor()->GetObjectManager()->FindObject(m_MouseOverObject);
|
||||
if (pOldObj)
|
||||
{
|
||||
pOldObj->SetHighlight(false);
|
||||
}
|
||||
|
||||
CBaseObject* pHitObj = GetIEditor()->GetObjectManager()->FindObject(hitGUID);
|
||||
if (pHitObj)
|
||||
{
|
||||
pHitObj->SetHighlight(true);
|
||||
}
|
||||
|
||||
m_MouseOverObject = hitGUID;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRuler::OnLButtonUp(CViewport* pView, QPoint& point, [[maybe_unused]] int flags)
|
||||
{
|
||||
if (m_startPoint.IsEmpty())
|
||||
{
|
||||
UpdateRulerPoint(pView, point, m_startPoint, false);
|
||||
}
|
||||
else if (m_endPoint.IsEmpty())
|
||||
{
|
||||
UpdateRulerPoint(pView, point, m_endPoint, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateRulerPoint(pView, point, m_startPoint, false);
|
||||
m_endPoint.Reset();
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Ruler helper for Editor to determine distances
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTIL_RULER_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_RULER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "RulerPoint.h"
|
||||
|
||||
//! The Ruler utility helps to determine distances between user-specified points
|
||||
class CRuler
|
||||
{
|
||||
public:
|
||||
CRuler();
|
||||
~CRuler();
|
||||
|
||||
//! Returns if ruler has queued paths in the path agent
|
||||
bool HasQueuedPaths() const;
|
||||
|
||||
//! Activate the ruler
|
||||
void SetActive(bool bActive);
|
||||
bool IsActive() const { return m_bActive; }
|
||||
|
||||
//! Update
|
||||
void Update();
|
||||
|
||||
//! Mouse callback handling from viewport
|
||||
bool MouseCallback(CViewport* pView, EMouseEvent event, QPoint& point, int flags);
|
||||
|
||||
private:
|
||||
//! Mouse callback helpers
|
||||
void OnMouseMove(CViewport* pView, QPoint& point, int flags);
|
||||
void OnLButtonUp(CViewport* pView, QPoint& point, int flags);
|
||||
|
||||
//! Returns world point based on mouse point
|
||||
void UpdateRulerPoint(CViewport* pView, const QPoint& point, CRulerPoint& rulerPoint, bool bRequestPath);
|
||||
|
||||
//! Request a path using the path agent
|
||||
void RequestPath();
|
||||
|
||||
bool IsObjectSelectMode(CViewport* pView) const;
|
||||
|
||||
private:
|
||||
bool m_bActive;
|
||||
GUID m_MouseOverObject;
|
||||
|
||||
// Base point
|
||||
CRulerPoint m_startPoint;
|
||||
CRulerPoint m_endPoint;
|
||||
|
||||
float m_sphereScale;
|
||||
float m_sphereTrans;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_RULER_H
|
||||
@@ -1,216 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Ruler helper for Editor to determine distances
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "RulerPoint.h"
|
||||
|
||||
// Editor
|
||||
#include "Objects/BaseObject.h"
|
||||
#include "Include/IObjectManager.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CRulerPoint::CRulerPoint()
|
||||
: m_type(eType_Invalid)
|
||||
, m_vPoint(ZERO)
|
||||
, m_ObjectGUID(GUID_NULL)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CRulerPoint& CRulerPoint::operator =(CRulerPoint const& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
Reset(); // Manage deselect of current object, etc.
|
||||
|
||||
m_type = other.m_type;
|
||||
m_vPoint = other.m_vPoint;
|
||||
m_ObjectGUID = other.m_ObjectGUID;
|
||||
m_sphereScale = other.m_sphereScale;
|
||||
m_sphereTrans = other.m_sphereTrans;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRulerPoint::Reset()
|
||||
{
|
||||
// Kill highlight of current object
|
||||
CBaseObject* pObject = GetObject();
|
||||
if (pObject)
|
||||
{
|
||||
pObject->SetHighlight(false);
|
||||
}
|
||||
|
||||
m_type = eType_Invalid;
|
||||
m_vPoint.zero();
|
||||
m_ObjectGUID = GUID_NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRulerPoint::Render(IRenderer* pRenderer)
|
||||
{
|
||||
CRY_ASSERT(pRenderer);
|
||||
IRenderAuxGeom* pAuxGeom = pRenderer->GetIRenderAuxGeom();
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case eType_Point:
|
||||
{
|
||||
Vec3 vOffset(0.1f, 0.1f, 0.1f);
|
||||
pAuxGeom->SetRenderFlags(e_Def3DPublicRenderflags | e_AlphaBlended);
|
||||
pAuxGeom->DrawSphere(m_vPoint, m_sphereScale, ColorF(1, 1, 1, m_sphereTrans));
|
||||
pAuxGeom->DrawAABB(AABB(m_vPoint - vOffset * m_sphereScale, m_vPoint + vOffset * m_sphereScale), false, ColorF(0.0f, 1.0f, 0.0f, 1.0f), eBBD_Faceted);
|
||||
}
|
||||
break;
|
||||
|
||||
case eType_Object:
|
||||
{
|
||||
CBaseObject* pObject = GetObject();
|
||||
if (pObject)
|
||||
{
|
||||
pObject->SetHighlight(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return; // No extra drawing
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRulerPoint::Set(const Vec3& vPos)
|
||||
{
|
||||
Reset();
|
||||
|
||||
m_type = eType_Point;
|
||||
m_vPoint = vPos;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRulerPoint::Set(CBaseObject* pObject)
|
||||
{
|
||||
Reset();
|
||||
|
||||
m_type = eType_Object;
|
||||
m_ObjectGUID = (pObject ? pObject->GetId() : GUID_NULL);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRulerPoint::SetHelperSettings(float scale, float trans)
|
||||
{
|
||||
m_sphereScale = scale;
|
||||
m_sphereTrans = trans;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CRulerPoint::IsEmpty() const
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case eType_Invalid:
|
||||
bResult = true;
|
||||
break;
|
||||
|
||||
case eType_Point:
|
||||
bResult = m_vPoint.IsZero();
|
||||
break;
|
||||
|
||||
case eType_Object:
|
||||
bResult = (GetObject() == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 CRulerPoint::GetPos() const
|
||||
{
|
||||
Vec3 vResult(ZERO);
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case eType_Point:
|
||||
vResult = m_vPoint;
|
||||
break;
|
||||
|
||||
case eType_Object:
|
||||
{
|
||||
CBaseObject* pObject = GetObject();
|
||||
if (pObject)
|
||||
{
|
||||
vResult = pObject->GetWorldPos();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return vResult;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 CRulerPoint::GetMidPoint(const CRulerPoint& otherPoint) const
|
||||
{
|
||||
Vec3 vResult(ZERO);
|
||||
|
||||
if (!IsEmpty() && !otherPoint.IsEmpty())
|
||||
{
|
||||
vResult = GetPos() + (otherPoint.GetPos() - GetPos()) * 0.5f;
|
||||
}
|
||||
else if (!IsEmpty())
|
||||
{
|
||||
vResult = GetPos();
|
||||
}
|
||||
else
|
||||
{
|
||||
vResult = otherPoint.GetPos();
|
||||
}
|
||||
|
||||
return vResult;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float CRulerPoint::GetDistance(const CRulerPoint& otherPoint) const
|
||||
{
|
||||
float fResult = 0.0f;
|
||||
|
||||
if (!IsEmpty() && !otherPoint.IsEmpty())
|
||||
{
|
||||
fResult = GetPos().GetDistance(otherPoint.GetPos());
|
||||
}
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseObject* CRulerPoint::GetObject() const
|
||||
{
|
||||
CBaseObject* pResult = NULL;
|
||||
|
||||
if (m_type == eType_Object)
|
||||
{
|
||||
pResult = GetIEditor()->GetObjectManager()->FindObject(m_ObjectGUID);
|
||||
}
|
||||
|
||||
return pResult;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Ruler point helper, used by CRuler
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTIL_RULERPOINT_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_RULERPOINT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class CRuler;
|
||||
|
||||
//! Ruler point helper - Defines a point for the ruler
|
||||
class CRulerPoint
|
||||
{
|
||||
public:
|
||||
CRulerPoint();
|
||||
CRulerPoint& operator =(CRulerPoint const& other);
|
||||
|
||||
void Reset();
|
||||
void Render(IRenderer* pRenderer);
|
||||
|
||||
//! Set helpers
|
||||
void Set(const Vec3& vPos);
|
||||
void Set(CBaseObject* pObject);
|
||||
void SetHelperSettings(float scale, float trans);
|
||||
|
||||
//! Returns is point has valid data in it (in use)
|
||||
bool IsEmpty() const;
|
||||
|
||||
//! Helpers to get correct data out
|
||||
Vec3 GetPos() const;
|
||||
Vec3 GetMidPoint(const CRulerPoint& otherPoint) const;
|
||||
float GetDistance(const CRulerPoint& otherPoint) const;
|
||||
CBaseObject* GetObject() const;
|
||||
|
||||
private:
|
||||
enum EType
|
||||
{
|
||||
eType_Invalid,
|
||||
eType_Point,
|
||||
eType_Object,
|
||||
|
||||
eType_COUNT,
|
||||
};
|
||||
EType m_type;
|
||||
|
||||
Vec3 m_vPoint;
|
||||
GUID m_ObjectGUID;
|
||||
float m_sphereScale;
|
||||
float m_sphereTrans;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_RULERPOINT_H
|
||||
Reference in New Issue
Block a user