mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-02-16 08:52:36 +00:00
added Im3d integration
This commit is contained in:
parent
16a51506c0
commit
75466f3be0
33 changed files with 5599 additions and 20 deletions
|
@ -18,13 +18,14 @@ You should have received a copy of the GNU General Public License
|
|||
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||
===========================================================================
|
||||
*/
|
||||
// Dear ImGui client integration and utility functions
|
||||
// Dear ImGui and Im3d client integration and utility functions
|
||||
|
||||
|
||||
#include "client.h"
|
||||
#include "cl_imgui.h"
|
||||
#include "../imgui/font_proggy_clean.h"
|
||||
#include "../imgui/font_sweet16_mono.h"
|
||||
#include "../im3d/im3d.h"
|
||||
|
||||
|
||||
static int keyMap[256];
|
||||
|
@ -723,6 +724,12 @@ void CL_IMGUI_MouseEvent(int dx, int dy)
|
|||
|
||||
qbool CL_IMGUI_KeyEvent(int key, qbool down, const char* cmd)
|
||||
{
|
||||
static bool shiftDown = false;
|
||||
if(key == K_SHIFT)
|
||||
{
|
||||
shiftDown = down != qfalse;
|
||||
}
|
||||
|
||||
if(down)
|
||||
{
|
||||
if(cmd != NULL)
|
||||
|
@ -769,7 +776,35 @@ qbool CL_IMGUI_KeyEvent(int key, qbool down, const char* cmd)
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(!io.WantCaptureMouse)
|
||||
{
|
||||
Im3d::AppData& ad = Im3d::GetAppData();
|
||||
switch(key)
|
||||
{
|
||||
case K_MOUSE1:
|
||||
ad.m_keyDown[Im3d::Action_Select] = !!down;
|
||||
break;
|
||||
case 'l':
|
||||
ad.m_keyDown[Im3d::Action_GizmoLocal] = shiftDown && !!down;
|
||||
break;
|
||||
case 't':
|
||||
ad.m_keyDown[Im3d::Action_GizmoTranslation] = shiftDown && !!down;
|
||||
break;
|
||||
case 'r':
|
||||
ad.m_keyDown[Im3d::Action_GizmoRotation] = shiftDown && !!down;
|
||||
break;
|
||||
case 's':
|
||||
ad.m_keyDown[Im3d::Action_GizmoScale] = shiftDown && !!down;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ad.m_snapTranslation = shiftDown ? 4.0f : 0.0f;
|
||||
ad.m_snapRotation = shiftDown ? DEG2RAD(30.0f) : 0.0f;
|
||||
ad.m_snapScale = shiftDown ? 0.5f : 0.0f;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
|
|||
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||
===========================================================================
|
||||
*/
|
||||
// Dear ImGui client integration and utility functions
|
||||
// Dear ImGui and Im3d client integration and utility functions
|
||||
|
||||
|
||||
#pragma once
|
||||
|
@ -53,7 +53,8 @@ const char* OpenFolderDialog_GetPath();
|
|||
#define MAIN_MENU_LIST(M) \
|
||||
M(Tools, "Tools") \
|
||||
M(Info, "Information") \
|
||||
M(Perf, "Performance")
|
||||
M(Perf, "Performance") \
|
||||
M(Im3D, "Im3D")
|
||||
|
||||
#define M(Enum, Desc) Enum,
|
||||
struct GUI_MainMenu
|
||||
|
|
19
code/im3d/LICENSE
Normal file
19
code/im3d/LICENSE
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2016-2022 John Chapman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
3366
code/im3d/im3d.cpp
Normal file
3366
code/im3d/im3d.cpp
Normal file
File diff suppressed because it is too large
Load diff
887
code/im3d/im3d.h
Normal file
887
code/im3d/im3d.h
Normal file
|
@ -0,0 +1,887 @@
|
|||
#pragma once
|
||||
|
||||
// Define IM3D_CONFIG "myfilename.h" from your build system if you do not want to modify im3d_config.h directly.
|
||||
#ifdef IM3D_CONFIG
|
||||
#include IM3D_CONFIG
|
||||
#else
|
||||
#include "im3d_config.h"
|
||||
#endif
|
||||
|
||||
#define IM3D_VERSION "1.16"
|
||||
|
||||
#ifndef IM3D_API
|
||||
#define IM3D_API
|
||||
#endif
|
||||
|
||||
#ifndef IM3D_ASSERT
|
||||
#include <cassert>
|
||||
#define IM3D_ASSERT(e) assert(e)
|
||||
#endif
|
||||
|
||||
#ifndef IM3D_VERTEX_ALIGNMENT
|
||||
#define IM3D_VERTEX_ALIGNMENT 4
|
||||
#endif
|
||||
|
||||
#include <cstdarg> // va_list
|
||||
|
||||
namespace Im3d {
|
||||
|
||||
typedef unsigned int U32;
|
||||
struct Vec2;
|
||||
struct Vec3;
|
||||
struct Vec4;
|
||||
struct Mat3;
|
||||
struct Mat4;
|
||||
struct Color;
|
||||
struct VertexData;
|
||||
struct AppData;
|
||||
struct DrawList;
|
||||
struct TextDrawList;
|
||||
struct Context;
|
||||
|
||||
typedef U32 Id;
|
||||
constexpr Id Id_Invalid = 0;
|
||||
|
||||
// Get AppData struct from the current context, fill before calling NewFrame().
|
||||
IM3D_API AppData& GetAppData();
|
||||
|
||||
// Call at the start of each frame, after filling the AppData struct.
|
||||
IM3D_API void NewFrame();
|
||||
// Call after all Im3d calls have been made for the current frame, before accessing draw data.
|
||||
IM3D_API void EndFrame();
|
||||
|
||||
// Access draw data. Draw lists are valid after calling EndFrame() and before calling NewFrame().
|
||||
IM3D_API const DrawList* GetDrawLists();
|
||||
IM3D_API U32 GetDrawListCount();
|
||||
|
||||
// Access to text draw data. Draw lists are valid after calling EndFrame() and before calling NewFrame().
|
||||
IM3D_API const TextDrawList* GetTextDrawLists();
|
||||
IM3D_API U32 GetTextDrawListCount();
|
||||
|
||||
// DEPRECATED (use EndFrame() + GetDrawLists()).
|
||||
// Call after all Im3d calls have been made for the current frame.
|
||||
IM3D_API void Draw();
|
||||
|
||||
|
||||
// Begin/end primitive. End() must be called before starting each new primitive type.
|
||||
IM3D_API void BeginPoints();
|
||||
IM3D_API void BeginLines();
|
||||
IM3D_API void BeginLineLoop();
|
||||
IM3D_API void BeginLineStrip();
|
||||
IM3D_API void BeginTriangles();
|
||||
IM3D_API void BeginTriangleStrip();
|
||||
IM3D_API void End();
|
||||
|
||||
// Add a vertex to the current primitive (call between Begin*() and End()).
|
||||
IM3D_API void Vertex(const Vec3& _position);
|
||||
IM3D_API void Vertex(const Vec3& _position, Color _color);
|
||||
IM3D_API void Vertex(const Vec3& _position, float _size);
|
||||
IM3D_API void Vertex(const Vec3& _position, float _size, Color _color);
|
||||
IM3D_API void Vertex(float _x, float _y, float _z);
|
||||
IM3D_API void Vertex(float _x, float _y, float _z, Color _color);
|
||||
IM3D_API void Vertex(float _x, float _y, float _z, float _size);
|
||||
IM3D_API void Vertex(float _x, float _y, float _z, float _size, Color _color);
|
||||
|
||||
// Color draw state (per vertex).
|
||||
IM3D_API void PushColor(); // push the stack top
|
||||
IM3D_API void PushColor(Color _color);
|
||||
IM3D_API void PopColor();
|
||||
IM3D_API void SetColor(Color _color);
|
||||
IM3D_API void SetColor(float _r, float _g, float _b, float _a = 1.0f);
|
||||
IM3D_API Color GetColor();
|
||||
|
||||
// Alpha draw state, multiplies the alpha set by the color draw state (per vertex).
|
||||
IM3D_API void PushAlpha(); // push the stack top
|
||||
IM3D_API void PushAlpha(float _alpha);
|
||||
IM3D_API void PopAlpha();
|
||||
IM3D_API void SetAlpha(float _alpha);
|
||||
IM3D_API float GetAlpha();
|
||||
|
||||
// Size draw state, for points/lines this is the radius/width in pixels (per vertex).
|
||||
IM3D_API void PushSize(); // push the stack top
|
||||
IM3D_API void PushSize(float _size);
|
||||
IM3D_API void PopSize();
|
||||
IM3D_API void SetSize(float _size);
|
||||
IM3D_API float GetSize();
|
||||
|
||||
// Sorting draw state, enable depth sorting between primitives (per primitive).
|
||||
IM3D_API void PushEnableSorting(); // push the stack top
|
||||
IM3D_API void PushEnableSorting(bool _enable);
|
||||
IM3D_API void PopEnableSorting();
|
||||
IM3D_API void EnableSorting(bool _enable);
|
||||
|
||||
// Push/pop all draw states (color, alpha, size, sorting).
|
||||
IM3D_API void PushDrawState();
|
||||
IM3D_API void PopDrawState();
|
||||
|
||||
// Transform state (per vertex).
|
||||
IM3D_API void PushMatrix(); // push stack top
|
||||
IM3D_API void PushMatrix(const Mat4& _mat4);
|
||||
IM3D_API void PopMatrix();
|
||||
IM3D_API void SetMatrix(const Mat4& _mat4);
|
||||
IM3D_API void SetIdentity();
|
||||
IM3D_API void MulMatrix(const Mat4& _mat4);
|
||||
IM3D_API void Translate(float _x, float _y, float _z);
|
||||
IM3D_API void Translate(const Vec3& _vec3);
|
||||
IM3D_API void Rotate(const Vec3& _axis, float _angle);
|
||||
IM3D_API void Rotate(const Mat3& _rotation);
|
||||
IM3D_API void Scale(float _x, float _y, float _z);
|
||||
|
||||
// High order shapes. Where _detail = -1, an automatic level of detail is chosen based on the distance to the view origin (as specified via the AppData struct).
|
||||
IM3D_API void DrawXyzAxes();
|
||||
IM3D_API void DrawPoint(const Vec3& _position, float _size, Color _color);
|
||||
IM3D_API void DrawLine(const Vec3& _a, const Vec3& _b, float _size, Color _color);
|
||||
IM3D_API void DrawQuad(const Vec3& _a, const Vec3& _b, const Vec3& _c, const Vec3& _d);
|
||||
IM3D_API void DrawQuad(const Vec3& _origin, const Vec3& _normal, const Vec2& _size);
|
||||
IM3D_API void DrawQuadFilled(const Vec3& _a, const Vec3& _b, const Vec3& _c, const Vec3& _d);
|
||||
IM3D_API void DrawQuadFilled(const Vec3& _origin, const Vec3& _normal, const Vec2& _size);
|
||||
IM3D_API void DrawCircle(const Vec3& _origin, const Vec3& _normal, float _radius, int _detail = -1);
|
||||
IM3D_API void DrawCircleFilled(const Vec3& _origin, const Vec3& _normal, float _radius, int _detail = -1);
|
||||
IM3D_API void DrawSphere(const Vec3& _origin, float _radius, int _detail = -1);
|
||||
IM3D_API void DrawSphereFilled(const Vec3& _origin, float _radius, int _detail = -1);
|
||||
IM3D_API void DrawAlignedBox(const Vec3& _min, const Vec3& _max);
|
||||
IM3D_API void DrawAlignedBoxFilled(const Vec3& _min, const Vec3& _max);
|
||||
IM3D_API void DrawCylinder(const Vec3& _start, const Vec3& _end, float _radius, int _detail = -1);
|
||||
IM3D_API void DrawCapsule(const Vec3& _start, const Vec3& _end, float _radius, int _detail = -1);
|
||||
IM3D_API void DrawPrism(const Vec3& _start, const Vec3& _end, float _radius, int _sides);
|
||||
IM3D_API void DrawArrow(const Vec3& _start, const Vec3& _end, float _headLength = -1.0f, float _headThickness = -1.0f);
|
||||
IM3D_API void DrawCone(const Vec3& _origin, const Vec3& _normal,float height, float _radius, int _detail);
|
||||
IM3D_API void DrawConeFilled(const Vec3& _origin, const Vec3& _normal,float height, float _radius, int _detail);
|
||||
|
||||
// Add text. See TextFlags_ enum for _textFlags. _size is a hint to the application-side text rendering.
|
||||
IM3D_API void Text(const Vec3& _position, U32 _textFlags, const char* _text, ...); // use the current draw state for size/color
|
||||
IM3D_API void Text(const Vec3& _position, float _size, Color _color, U32 _textFlags, const char* _text, ...);
|
||||
|
||||
// IDs are used to uniquely identify gizmos and layers. Gizmo should have a unique ID during a frame.
|
||||
// Note that ids are a hash of the whole ID stack, see PushId(), PopId().
|
||||
IM3D_API Id MakeId(const char* _str);
|
||||
IM3D_API Id MakeId(const void* _ptr);
|
||||
IM3D_API Id MakeId(int _i);
|
||||
|
||||
// PushId(), PopId() affect the result of subsequent calls to MakeId(), use when creating gizmos in a loop.
|
||||
IM3D_API void PushId(); // push stack top
|
||||
IM3D_API void PushId(Id _id);
|
||||
IM3D_API void PushId(const char* _str);
|
||||
IM3D_API void PushId(const void* _ptr);
|
||||
IM3D_API void PushId(int _i);
|
||||
IM3D_API void PopId();
|
||||
IM3D_API Id GetId();
|
||||
|
||||
// Layer id state, subsequent primitives are added to a separate draw list associated with the id (per primitive).
|
||||
IM3D_API void PushLayerId(Id _layer);
|
||||
IM3D_API void PushLayerId(const char* _str); // calls PushLayerId(MakeId(_str))
|
||||
IM3D_API void PopLayerId();
|
||||
IM3D_API Id GetLayerId();
|
||||
|
||||
// Manipulate translation/rotation/scale via a gizmo. Return true if the gizmo is 'active' (if it modified the output parameter).
|
||||
// If _local is true, the Gizmo* functions expect that the local matrix is on the matrix stack; in general the application should
|
||||
// push the local matrix before calling any of the following.
|
||||
IM3D_API bool GizmoTranslation(const char* _id, float _translation_[3], bool _local = false);
|
||||
IM3D_API bool GizmoRotation(const char* _id, float _rotation_[3*3], bool _local = false);
|
||||
IM3D_API bool GizmoScale(const char* _id, float _scale_[3]); // local scale only
|
||||
// Unified gizmo, selects local/global, translation/rotation/scale based on the context-global gizmo modes. Return true if the gizmo is active.
|
||||
IM3D_API bool Gizmo(const char* _id, float _translation_[3], float _rotation_[3*3], float _scale_[3]); // any of _translation_/_rotation_/_scale_ may be null.
|
||||
IM3D_API bool Gizmo(const char* _id, float _transform_[4*4]);
|
||||
|
||||
// Gizmo* overloads which take an ID directly. In some cases the app may want to call MakeId() separately, usually to change the gizmo appearance if hot/active.
|
||||
IM3D_API bool GizmoTranslation(Id _id, float _translation_[3], bool _local = false);
|
||||
IM3D_API bool GizmoRotation(Id _id, float _rotation_[3*3], bool _local = false);
|
||||
IM3D_API bool GizmoScale(Id _id, float _scale_[3]);
|
||||
IM3D_API bool Gizmo(Id _id, float _transform_[4*4]);
|
||||
IM3D_API bool Gizmo(Id _id, float _translation_[3], float _rotation_[3*3], float _scale_[3]);
|
||||
|
||||
// Active gizmo ID. This will match the _id parameter passed to a Gizmo* function. Return Id_Invalid if no gizmo is in use.
|
||||
IM3D_API Id GetActiveId();
|
||||
// ID of the current current 'hot' gizmo (nearest intersecting gizmo along the cursor ray).
|
||||
IM3D_API Id GetHotId();
|
||||
|
||||
// Visibility tests. The application must set a culling frustum via AppData.
|
||||
IM3D_API bool IsVisible(const Vec3& _origin, float _radius); // sphere
|
||||
IM3D_API bool IsVisible(const Vec3& _min, const Vec3& _max); // axis-aligned bounding box
|
||||
|
||||
// Get/set the current context. All Im3d calls affect the currently bound context.
|
||||
IM3D_API Context& GetContext();
|
||||
IM3D_API void SetContext(Context& _ctx);
|
||||
|
||||
// Merge vertex data from _src into _dst_. Layers are preserved. Call before EndFrame().
|
||||
IM3D_API void MergeContexts(Context& _dst_, const Context& _src);
|
||||
|
||||
|
||||
struct IM3D_API Vec2
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Vec2() {}
|
||||
Vec2(float _xy): x(_xy), y(_xy) {}
|
||||
Vec2(float _x, float _y): x(_x), y(_y) {}
|
||||
|
||||
operator float*() { return &x; }
|
||||
operator const float*() const { return &x; }
|
||||
|
||||
#ifdef IM3D_VEC2_APP
|
||||
IM3D_VEC2_APP
|
||||
#endif
|
||||
};
|
||||
|
||||
struct IM3D_API Vec3
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
Vec3() {}
|
||||
Vec3(float _xyz): x(_xyz), y(_xyz), z(_xyz) {}
|
||||
Vec3(float _x, float _y, float _z): x(_x), y(_y), z(_z) {}
|
||||
Vec3(const Vec2& _xy, float _z): x(_xy.x), y(_xy.y), z(_z) {}
|
||||
Vec3(const Vec4& _v); // discards w
|
||||
|
||||
operator float*() { return &x; }
|
||||
operator const float*() const { return &x; }
|
||||
|
||||
#ifdef IM3D_VEC3_APP
|
||||
IM3D_VEC3_APP
|
||||
#endif
|
||||
};
|
||||
|
||||
struct IM3D_API Vec4
|
||||
{
|
||||
float x, y, z, w;
|
||||
|
||||
Vec4() {}
|
||||
Vec4(float _xyzw): x(_xyzw), y(_xyzw), z(_xyzw), w(_xyzw) {}
|
||||
Vec4(float _x, float _y, float _z, float _w): x(_x), y(_y), z(_z), w(_w) {}
|
||||
Vec4(const Vec3& _xyz, float _w): x(_xyz.x), y(_xyz.y), z(_xyz.z), w(_w) {}
|
||||
Vec4(Color _rgba);
|
||||
|
||||
operator float*() { return &x; }
|
||||
operator const float*() const { return &x; }
|
||||
|
||||
#ifdef IM3D_VEC4_APP
|
||||
IM3D_VEC4_APP
|
||||
#endif
|
||||
};
|
||||
|
||||
struct IM3D_API Mat3
|
||||
{
|
||||
float m[3*3]; // column-major unless IM3D_MATRIX_ROW_MAJOR defined
|
||||
|
||||
Mat3() {}
|
||||
Mat3(float _diagonal);
|
||||
Mat3(
|
||||
float m00, float m01, float m02,
|
||||
float m10, float m11, float m12,
|
||||
float m20, float m21, float m22
|
||||
);
|
||||
Mat3(const Vec3& _colX, const Vec3& _colY, const Vec3& _colZ);
|
||||
Mat3(const Mat4& _mat4); // extract upper 3x3
|
||||
|
||||
operator float*() { return m; }
|
||||
operator const float*() const { return m; }
|
||||
|
||||
Vec3 getCol(int _i) const;
|
||||
Vec3 getRow(int _i) const;
|
||||
void setCol(int _i, const Vec3& _v);
|
||||
void setRow(int _i, const Vec3& _v);
|
||||
|
||||
Vec3 getScale() const;
|
||||
void setScale(const Vec3& _scale);
|
||||
|
||||
float operator()(int _row, int _col) const
|
||||
{
|
||||
#ifdef IM3D_MATRIX_ROW_MAJOR
|
||||
int i = _row * 3 + _col;
|
||||
#else
|
||||
int i = _col * 3 + _row;
|
||||
#endif
|
||||
return m[i];
|
||||
}
|
||||
float& operator()(int _row, int _col)
|
||||
{
|
||||
#ifdef IM3D_MATRIX_ROW_MAJOR
|
||||
int i = _row * 3 + _col;
|
||||
#else
|
||||
int i = _col * 3 + _row;
|
||||
#endif
|
||||
return m[i];
|
||||
}
|
||||
|
||||
#ifdef IM3D_MAT3_APP
|
||||
IM3D_MAT3_APP
|
||||
#endif
|
||||
};
|
||||
|
||||
struct IM3D_API Mat4
|
||||
{
|
||||
float m[4*4]; // column-major unless IM3D_MATRIX_ROW_MAJOR defined
|
||||
|
||||
Mat4() {}
|
||||
Mat4(float _diagonal);
|
||||
Mat4(
|
||||
float m00, float m01, float m02, float m03,
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23,
|
||||
float m30 = 0.0f, float m31 = 0.0f, float m32 = 0.0f, float m33 = 1.0f
|
||||
);
|
||||
Mat4(const Mat3& _mat3);
|
||||
Mat4(const Vec3& _translation, const Mat3& _rotation, const Vec3& _scale);
|
||||
|
||||
operator float*() { return m; }
|
||||
operator const float*() const { return m; }
|
||||
|
||||
Vec4 getCol(int _i) const;
|
||||
Vec4 getRow(int _i) const;
|
||||
void setCol(int _i, const Vec4& _v);
|
||||
void setRow(int _i, const Vec4& _v);
|
||||
|
||||
Vec3 getTranslation() const;
|
||||
void setTranslation(const Vec3& _translation);
|
||||
Mat3 getRotation() const;
|
||||
void setRotation(const Mat3& _rotation);
|
||||
Vec3 getScale() const;
|
||||
void setScale(const Vec3& _scale);
|
||||
|
||||
float operator()(int _row, int _col) const
|
||||
{
|
||||
#ifdef IM3D_MATRIX_ROW_MAJOR
|
||||
int i = _row * 4 + _col;
|
||||
#else
|
||||
int i = _col * 4 + _row;
|
||||
#endif
|
||||
return m[i];
|
||||
}
|
||||
float& operator()(int _row, int _col)
|
||||
{
|
||||
#ifdef IM3D_MATRIX_ROW_MAJOR
|
||||
int i = _row * 4 + _col;
|
||||
#else
|
||||
int i = _col * 4 + _row;
|
||||
#endif
|
||||
return m[i];
|
||||
}
|
||||
|
||||
#ifdef IM3D_MAT4_APP
|
||||
IM3D_MAT4_APP
|
||||
#endif
|
||||
};
|
||||
|
||||
struct IM3D_API Color
|
||||
{
|
||||
U32 v; // rgba8 (MSB = r)
|
||||
|
||||
constexpr Color(): v(0) {}
|
||||
constexpr Color(U32 _rgba): v(_rgba) {}
|
||||
Color(const Vec4& _rgba);
|
||||
Color(const Vec3& _rgb, float _alpha);
|
||||
Color(float _r, float _g, float _b, float _a = 1.0f);
|
||||
|
||||
operator U32() const { return v; }
|
||||
|
||||
void set(int _i, float _val)
|
||||
{
|
||||
_i *= 8;
|
||||
U32 mask = 0xff << _i;
|
||||
v = (v & ~mask) | (U32(_val * 255.0f) << _i);
|
||||
}
|
||||
void setR(float _val) { set(3, _val); }
|
||||
void setG(float _val) { set(2, _val); }
|
||||
void setB(float _val) { set(1, _val); }
|
||||
void setA(float _val) { set(0, _val); }
|
||||
|
||||
float get(int _i) const
|
||||
{
|
||||
_i *= 8;
|
||||
U32 mask = 0xff << _i;
|
||||
return float((v & mask) >> _i) / 255.0f;
|
||||
}
|
||||
float getR() const { return get(3); }
|
||||
float getG() const { return get(2); }
|
||||
float getB() const { return get(1); }
|
||||
float getA() const { return get(0); }
|
||||
|
||||
U32 getABGR() const
|
||||
{
|
||||
return 0
|
||||
| ((v & (0xff << 24)) >> 24) // r
|
||||
| ((v & (0xff << 16)) >> 8) // g
|
||||
| ((v & (0xff << 8)) << 8) // b
|
||||
| ((v & (0xff )) << 24) // a
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr Color Color_Black = Color(0x000000ff);
|
||||
constexpr Color Color_White = Color(0xffffffff);
|
||||
constexpr Color Color_Gray = Color(0x808080ff);
|
||||
constexpr Color Color_Red = Color(0xff0000ff);
|
||||
constexpr Color Color_Green = Color(0x00ff00ff);
|
||||
constexpr Color Color_Blue = Color(0x0000ffff);
|
||||
constexpr Color Color_Magenta = Color(0xff00ffff);
|
||||
constexpr Color Color_Yellow = Color(0xffff00ff);
|
||||
constexpr Color Color_Cyan = Color(0x00ffffff);
|
||||
|
||||
constexpr Color Color_Pink = Color(0xffc0cbff);
|
||||
constexpr Color Color_Orange = Color(0xffa500ff);
|
||||
constexpr Color Color_Gold = Color(0xffd700ff);
|
||||
constexpr Color Color_Brown = Color(0x8b4513ff);
|
||||
constexpr Color Color_Purple = Color(0x800080ff);
|
||||
constexpr Color Color_Teal = Color(0x008080ff);
|
||||
constexpr Color Color_Navy = Color(0x000080ff);
|
||||
|
||||
struct alignas(IM3D_VERTEX_ALIGNMENT) VertexData
|
||||
{
|
||||
Vec4 m_positionSize; // xyz = position, w = size
|
||||
Color m_color; // rgba8 (MSB = r)
|
||||
|
||||
VertexData() {}
|
||||
VertexData(const Vec3& _position, float _size, Color _color): m_positionSize(_position, _size), m_color(_color) {}
|
||||
};
|
||||
|
||||
enum DrawPrimitiveType
|
||||
{
|
||||
// order here determines the order in which unsorted primitives are drawn
|
||||
DrawPrimitive_Triangles,
|
||||
DrawPrimitive_Lines,
|
||||
DrawPrimitive_Points,
|
||||
|
||||
DrawPrimitive_Count
|
||||
};
|
||||
|
||||
struct DrawList
|
||||
{
|
||||
Id m_layerId;
|
||||
DrawPrimitiveType m_primType;
|
||||
const VertexData* m_vertexData;
|
||||
U32 m_vertexCount;
|
||||
};
|
||||
typedef void (DrawPrimitivesCallback)(const DrawList& _drawList);
|
||||
|
||||
enum TextFlags
|
||||
{
|
||||
TextFlags_AlignLeft = (1 << 0),
|
||||
TextFlags_AlignRight = (1 << 1),
|
||||
TextFlags_AlignTop = (1 << 3),
|
||||
TextFlags_AlignBottom = (1 << 4),
|
||||
|
||||
TextFlags_Default = 0 // align center
|
||||
};
|
||||
|
||||
struct alignas(IM3D_VERTEX_ALIGNMENT) TextData
|
||||
{
|
||||
Vec4 m_positionSize; // xyz = position, w = size
|
||||
Color m_color; // rgba8 (MSB = r)
|
||||
U32 m_flags; // TextFlags
|
||||
U32 m_textLength; // # chars in the text, excluding null terminator
|
||||
U32 m_textBufferOffset; // start of the text in the draw list's text buffer
|
||||
};
|
||||
|
||||
struct TextDrawList
|
||||
{
|
||||
Id m_layerId;
|
||||
const TextData* m_textData;
|
||||
U32 m_textDataCount;
|
||||
const char* m_textBuffer;
|
||||
};
|
||||
|
||||
enum Key
|
||||
{
|
||||
Mouse_Left,
|
||||
Key_L,
|
||||
Key_R,
|
||||
Key_S,
|
||||
Key_T,
|
||||
|
||||
Key_Count,
|
||||
|
||||
// the following map keys -> 'action' states which may be more intuitive
|
||||
Action_Select = Mouse_Left,
|
||||
Action_GizmoLocal = Key_L,
|
||||
Action_GizmoRotation = Key_R,
|
||||
Action_GizmoScale = Key_S,
|
||||
Action_GizmoTranslation = Key_T,
|
||||
|
||||
Action_Count
|
||||
};
|
||||
|
||||
enum FrustumPlane
|
||||
{
|
||||
FrustumPlane_Near,
|
||||
FrustumPlane_Far,
|
||||
FrustumPlane_Top,
|
||||
FrustumPlane_Right,
|
||||
FrustumPlane_Bottom,
|
||||
FrustumPlane_Left,
|
||||
|
||||
FrustumPlane_Count
|
||||
};
|
||||
|
||||
struct AppData
|
||||
{
|
||||
bool m_keyDown[Key_Count] = { false }; // Key states.
|
||||
Vec4 m_cullFrustum[FrustumPlane_Count] = { Vec4(0.0f) }; // Frustum planes for culling (if culling enabled).
|
||||
Vec3 m_cursorRayOrigin = Vec3(0.0f); // World space cursor ray origin.
|
||||
Vec3 m_cursorRayDirection = Vec3(0.0f); // World space cursor ray direction.
|
||||
Vec3 m_worldUp = Vec3(0.0f, 1.0f, 0.0f); // World space 'up' vector.
|
||||
Vec3 m_viewOrigin = Vec3(0.0f); // World space render origin (camera position).
|
||||
Vec3 m_viewDirection = Vec3(0.0f); // World space view direction.
|
||||
Vec2 m_viewportSize = Vec2(0.0f); // Viewport size (pixels).
|
||||
float m_projScaleY = 1.0f; // Scale factor used to convert from pixel size -> world scale; use tan(fov) for perspective projections, far plane height for ortho.
|
||||
bool m_projOrtho = false; // If the projection matrix is orthographic.
|
||||
float m_deltaTime = 0.0f; // Time since previous frame (seconds).
|
||||
float m_snapTranslation = 0.0f; // Snap value for translation gizmos (world units). 0 = disabled.
|
||||
float m_snapRotation = 0.0f; // Snap value for rotation gizmos (radians). 0 = disabled.
|
||||
float m_snapScale = 0.0f; // Snap value for scale gizmos. 0 = disabled.
|
||||
bool m_flipGizmoWhenBehind = true; // Flip gizmo axes when viewed from behind.
|
||||
void* m_appData = nullptr; // App-specific data.
|
||||
|
||||
DrawPrimitivesCallback* drawCallback = nullptr; // e.g. void Im3d_Draw(const DrawList& _drawList)
|
||||
|
||||
// Extract cull frustum planes from the view-projection matrix.
|
||||
// Set _ndcZNegativeOneToOne = true if the proj matrix maps z from [-1,1] (OpenGL style).
|
||||
void setCullFrustum(const Mat4& _viewProj, bool _ndcZNegativeOneToOne);
|
||||
};
|
||||
|
||||
// Minimal vector.
|
||||
template <typename T>
|
||||
struct Vector
|
||||
{
|
||||
Vector() {}
|
||||
~Vector();
|
||||
|
||||
T& operator[](U32 _i) { IM3D_ASSERT(_i < m_size); return m_data[_i]; }
|
||||
const T& operator[](U32 _i) const { IM3D_ASSERT(_i < m_size); return m_data[_i]; }
|
||||
T* data() { return m_data; }
|
||||
const T* data() const { return m_data; }
|
||||
|
||||
T& push_back() { if (m_size == m_capacity) { reserve(m_capacity + m_capacity / 2); } return m_data[m_size++]; }
|
||||
void push_back(const T& _v) { T tmp = _v; if (m_size == m_capacity) { reserve(m_capacity + m_capacity / 2); } m_data[m_size++] = tmp; }
|
||||
void pop_back() { IM3D_ASSERT(m_size > 0); --m_size; }
|
||||
void append(const T* _v, U32 _count);
|
||||
void append(const Vector<T>& _other) { append(_other.data(), _other.size()); }
|
||||
|
||||
T* begin() { return m_data; }
|
||||
const T* begin() const { return m_data; }
|
||||
T* end() { return m_data + m_size; }
|
||||
const T* end() const { return m_data + m_size; }
|
||||
T& front() { IM3D_ASSERT(m_size > 0); return m_data[0]; }
|
||||
const T& front() const { IM3D_ASSERT(m_size > 0); return m_data[0]; }
|
||||
T& back() { IM3D_ASSERT(m_size > 0); return m_data[m_size - 1]; }
|
||||
const T& back() const { IM3D_ASSERT(m_size > 0); return m_data[m_size - 1]; }
|
||||
|
||||
U32 size() const { return m_size; }
|
||||
U32 capacity() const { return m_capacity; }
|
||||
bool empty() const { return m_size == 0; }
|
||||
|
||||
void clear() { m_size = 0; }
|
||||
void reserve(U32 _capacity);
|
||||
void resize(U32 _size, const T& _val);
|
||||
void resize(U32 _size);
|
||||
|
||||
static void swap(Vector<T>& _a_, Vector<T>& _b_);
|
||||
|
||||
private:
|
||||
|
||||
T* m_data = nullptr;
|
||||
U32 m_size = 0;
|
||||
U32 m_capacity = 0;
|
||||
};
|
||||
|
||||
|
||||
enum PrimitiveMode
|
||||
{
|
||||
PrimitiveMode_None,
|
||||
PrimitiveMode_Points,
|
||||
PrimitiveMode_Lines,
|
||||
PrimitiveMode_LineStrip,
|
||||
PrimitiveMode_LineLoop,
|
||||
PrimitiveMode_Triangles,
|
||||
PrimitiveMode_TriangleStrip
|
||||
};
|
||||
enum GizmoMode
|
||||
{
|
||||
GizmoMode_Translation,
|
||||
GizmoMode_Rotation,
|
||||
GizmoMode_Scale
|
||||
};
|
||||
|
||||
// Context stores all relevant state - main interface affects the context currently bound via SetCurrentContext().
|
||||
struct IM3D_API Context
|
||||
{
|
||||
Context();
|
||||
~Context();
|
||||
|
||||
void begin(PrimitiveMode _mode);
|
||||
void end();
|
||||
|
||||
void vertex(const Vec3& _position, float _size, Color _color);
|
||||
void vertex(const Vec3& _position ) { vertex(_position, getSize(), getColor()); }
|
||||
|
||||
void text(const Vec3& _position, float _size, Color _color, TextFlags _flags, const char* _textStart, const char* _textEnd);
|
||||
void text(const Vec3& _position, float _size, Color _color, TextFlags _flags, const char* _text, va_list _args);
|
||||
|
||||
void reset();
|
||||
void merge(const Context& _src);
|
||||
void endFrame();
|
||||
void draw(); // DEPRECATED (see Im3d::Draw)
|
||||
|
||||
const DrawList* getDrawLists() const { return m_drawLists.data(); }
|
||||
U32 getDrawListCount() const { return m_drawLists.size(); }
|
||||
|
||||
const TextDrawList* getTextDrawLists() const { return m_textDrawLists.data(); }
|
||||
U32 getTextDrawListCount() const { return m_textDrawLists.size(); }
|
||||
|
||||
|
||||
void setColor(Color _color) { m_colorStack.back() = _color; }
|
||||
Color getColor() const { return m_colorStack.back(); }
|
||||
void pushColor(Color _color) { m_colorStack.push_back(_color); }
|
||||
void popColor() { IM3D_ASSERT(m_colorStack.size() > 1); m_colorStack.pop_back(); }
|
||||
|
||||
void setAlpha(float _alpha) { m_alphaStack.back() = _alpha; }
|
||||
float getAlpha() const { return m_alphaStack.back(); }
|
||||
void pushAlpha(float _alpha) { m_alphaStack.push_back(_alpha); }
|
||||
void popAlpha() { IM3D_ASSERT(m_alphaStack.size() > 1); m_alphaStack.pop_back(); }
|
||||
|
||||
void setSize(float _size) { m_sizeStack.back() = _size; }
|
||||
float getSize() const { return m_sizeStack.back(); }
|
||||
void pushSize(float _size) { m_sizeStack.push_back(_size); }
|
||||
void popSize() { IM3D_ASSERT(m_sizeStack.size() > 1); m_sizeStack.pop_back(); }
|
||||
|
||||
void setEnableSorting(bool _enable);
|
||||
bool getEnableSorting() const { return m_enableSortingStack.back(); }
|
||||
void pushEnableSorting(bool _enable);
|
||||
void popEnableSorting();
|
||||
|
||||
Id getLayerId() const { return m_layerIdStack.back(); }
|
||||
void pushLayerId(Id _layer);
|
||||
void popLayerId();
|
||||
|
||||
void setMatrix(const Mat4& _mat4) { m_matrixStack.back() = _mat4; }
|
||||
const Mat4& getMatrix() const { return m_matrixStack.back(); }
|
||||
void pushMatrix(const Mat4& _mat4) { m_matrixStack.push_back(_mat4); }
|
||||
void popMatrix() { IM3D_ASSERT(m_matrixStack.size() > 1); m_matrixStack.pop_back(); }
|
||||
|
||||
void setId(Id _id) { m_idStack.back() = _id; }
|
||||
Id getId() const { return m_idStack.back(); }
|
||||
void pushId(Id _id) { m_idStack.push_back(_id); }
|
||||
void popId() { IM3D_ASSERT(m_idStack.size() > 1); m_idStack.pop_back(); }
|
||||
|
||||
AppData& getAppData() { return m_appData; }
|
||||
|
||||
// Low-level interface for internal and app-defined gizmos. May be subject to breaking changes.
|
||||
|
||||
bool gizmoAxisTranslation_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldHeight, float _worldSize, Vec3* _out_);
|
||||
void gizmoAxisTranslation_Draw(Id _id, const Vec3& _origin, const Vec3& _axis, float _worldHeight, float _worldSize, Color _color);
|
||||
|
||||
bool gizmoPlaneTranslation_Behavior(Id _id, const Vec3& _origin, const Vec3& _normal, float _snap, float _worldSize, Vec3* _out_);
|
||||
void gizmoPlaneTranslation_Draw(Id _id, const Vec3& _origin, const Vec3& _normal, float _worldSize, Color _color);
|
||||
|
||||
bool gizmoAxislAngle_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldRadius, float _worldSize, float* _out_);
|
||||
void gizmoAxislAngle_Draw(Id _id, const Vec3& _origin, const Vec3& _axis, float _worldRadius, float _angle, Color _color, float _minAlpha);
|
||||
|
||||
bool gizmoAxisScale_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldHeight, float _worldSize, float *_out_);
|
||||
void gizmoAxisScale_Draw(Id _id, const Vec3& _origin, const Vec3& _axis, float _worldHeight, float _worldSize, Color _color);
|
||||
|
||||
// Convert pixels -> world space size based on distance between _position and view origin.
|
||||
float pixelsToWorldSize(const Vec3& _position, float _pixels);
|
||||
// Convert world space size -> pixels based on distance between _position and view origin.
|
||||
float worldSizeToPixels(const Vec3& _position, float _pixels);
|
||||
// Blend between _min and _max based on distance betwen _position and view origin.
|
||||
int estimateLevelOfDetail(const Vec3& _position, float _worldSize, int _min = 4, int _max = 256);
|
||||
|
||||
// Make _id hot if _depth < m_hotDepth && _intersects.
|
||||
bool makeHot(Id _id, float _depth, bool _intersects);
|
||||
// Make _id active.
|
||||
void makeActive(Id _id);
|
||||
// Reset the acive/hot ids and the hot depth.
|
||||
void resetId();
|
||||
|
||||
// Interpret key state.
|
||||
bool isKeyDown(Key _key) const { return m_keyDownCurr[_key]; }
|
||||
bool wasKeyPressed(Key _key) const { return m_keyDownCurr[_key] && !m_keyDownPrev[_key]; }
|
||||
|
||||
// Visibiity tests for culling.
|
||||
bool isVisible(const VertexData* _vdata, DrawPrimitiveType _prim); // per-vertex
|
||||
bool isVisible(const Vec3& _origin, float _radius); // sphere
|
||||
bool isVisible(const Vec3& _min, const Vec3& _max); // axis-aligned box
|
||||
|
||||
// Gizmo state.
|
||||
|
||||
bool m_gizmoLocal; // Global mode selection for gizmos.
|
||||
GizmoMode m_gizmoMode; // "
|
||||
Id m_activeId; // Currently active gizmo. If set, this is the same as m_hotId.
|
||||
Id m_hotId; // ID of the current 'hot' gizmo (nearest intersecting gizmo along the cursor ray). NB this is the id of the *sub* gizmo, not the app-specified ID.
|
||||
float m_hotDepth; // Depth of the current hot gizmo along the cursor ray, for handling occlusion.
|
||||
Id m_appId; // Current ID *without* the hashing the ID stack (= _id arg to Gizmo* functions).
|
||||
Id m_appActiveId; // Copied from m_appId for the current active gizmo.
|
||||
Id m_appHotId; // Copied from m_appId for the current 'hot' gizmo.
|
||||
Vec3 m_gizmoStateVec3; // Stored state for the active gizmo.
|
||||
Mat3 m_gizmoStateMat3; // "
|
||||
float m_gizmoStateFloat; // "
|
||||
float m_gizmoHeightPixels; // Height/radius of gizmos.
|
||||
float m_gizmoSizePixels; // Thickness of gizmo lines.
|
||||
|
||||
|
||||
// Stats, debugging.
|
||||
|
||||
// Return the total number of primitives (sorted + unsorted) of the given _type in all layers.
|
||||
U32 getPrimitiveCount(DrawPrimitiveType _type) const;
|
||||
|
||||
// Return the total number of text primitives in all layers.
|
||||
U32 getTextCount() const;
|
||||
|
||||
// Return the number of layers.
|
||||
U32 getLayerCount() const { return m_layerIdMap.size(); }
|
||||
|
||||
private:
|
||||
|
||||
// State stacks.
|
||||
Vector<Color> m_colorStack;
|
||||
Vector<float> m_alphaStack;
|
||||
Vector<float> m_sizeStack;
|
||||
Vector<bool> m_enableSortingStack;
|
||||
Vector<Mat4> m_matrixStack;
|
||||
Vector<Id> m_idStack;
|
||||
Vector<Id> m_layerIdStack;
|
||||
|
||||
// Vertex data: one list per layer, per primitive type, *2 for sorted/unsorted.
|
||||
typedef Vector<VertexData> VertexList;
|
||||
Vector<VertexList*> m_vertexData[2]; // Each layer is DrawPrimitive_Count consecutive lists.
|
||||
int m_vertexDataIndex; // 0, or 1 if sorting enabled.
|
||||
Vector<Id> m_layerIdMap; // Map Id -> vertex data index.
|
||||
int m_layerIndex; // Index of the currently active layer in m_layerIdMap.
|
||||
Vector<DrawList> m_drawLists; // All draw lists for the current frame, available after calling endFrame() before calling reset().
|
||||
bool m_sortCalled; // Avoid calling sort() during every call to draw().
|
||||
bool m_endFrameCalled; // For assert, if vertices are pushed after endFrame() was called.
|
||||
|
||||
// Text data: one list per layer.
|
||||
typedef Vector<TextData> TextList;
|
||||
Vector<TextList*> m_textData;
|
||||
Vector<char> m_textBuffer;
|
||||
Vector<TextDrawList> m_textDrawLists;
|
||||
|
||||
// Primitive state.
|
||||
PrimitiveMode m_primMode;
|
||||
DrawPrimitiveType m_primType;
|
||||
U32 m_firstVertThisPrim; // Index of the first vertex pushed during this primitive.
|
||||
U32 m_vertCountThisPrim; // # calls to vertex() since the last call to begin().
|
||||
Vec3 m_minVertThisPrim;
|
||||
Vec3 m_maxVertThisPrim;
|
||||
|
||||
// App data.
|
||||
AppData m_appData;
|
||||
bool m_keyDownCurr[Key_Count]; // Key state captured during reset().
|
||||
bool m_keyDownPrev[Key_Count]; // Key state from previous frame.
|
||||
Vec4 m_cullFrustum[FrustumPlane_Count]; // Optimized frustum planes from m_appData.m_cullFrustum.
|
||||
int m_cullFrustumCount; // # valid frustum planes in m_cullFrustum.
|
||||
|
||||
// Sort primitive data.
|
||||
void sort();
|
||||
|
||||
// Return -1 if _id not found.
|
||||
int findLayerIndex(Id _id) const;
|
||||
|
||||
// Access the current vertex/text data based on m_layerIndex.
|
||||
VertexList* getCurrentVertexList();
|
||||
TextList* getCurrentTextList();
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
#if IM3D_THREAD_LOCAL_CONTEXT_PTR
|
||||
#define IM3D_THREAD_LOCAL thread_local
|
||||
#else
|
||||
#define IM3D_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
extern IM3D_THREAD_LOCAL Context* g_CurrentContext;
|
||||
|
||||
}
|
||||
|
||||
inline AppData& GetAppData() { return GetContext().getAppData(); }
|
||||
inline void NewFrame() { GetContext().reset(); }
|
||||
inline void EndFrame() { GetContext().endFrame(); }
|
||||
inline void Draw() { GetContext().draw(); }
|
||||
|
||||
inline const DrawList* GetDrawLists() { return GetContext().getDrawLists(); }
|
||||
inline U32 GetDrawListCount() { return GetContext().getDrawListCount(); }
|
||||
|
||||
inline const TextDrawList* GetTextDrawLists() { return GetContext().getTextDrawLists(); }
|
||||
inline U32 GetTextDrawListCount() { return GetContext().getTextDrawListCount(); }
|
||||
|
||||
inline void BeginPoints() { GetContext().begin(PrimitiveMode_Points); }
|
||||
inline void BeginLines() { GetContext().begin(PrimitiveMode_Lines); }
|
||||
inline void BeginLineLoop() { GetContext().begin(PrimitiveMode_LineLoop); }
|
||||
inline void BeginLineStrip() { GetContext().begin(PrimitiveMode_LineStrip); }
|
||||
inline void BeginTriangles() { GetContext().begin(PrimitiveMode_Triangles); }
|
||||
inline void BeginTriangleStrip() { GetContext().begin(PrimitiveMode_TriangleStrip); }
|
||||
inline void End() { GetContext().end(); }
|
||||
|
||||
inline void Vertex(const Vec3& _position) { GetContext().vertex(_position, GetContext().getSize(), GetContext().getColor()); }
|
||||
inline void Vertex(const Vec3& _position, Color _color) { GetContext().vertex(_position, GetContext().getSize(), _color); }
|
||||
inline void Vertex(const Vec3& _position, float _size) { GetContext().vertex(_position, _size, GetContext().getColor()); }
|
||||
inline void Vertex(const Vec3& _position, float _size, Color _color) { GetContext().vertex(_position, _size, _color); }
|
||||
inline void Vertex(float _x, float _y, float _z) { Vertex(Vec3(_x, _y, _z)); }
|
||||
inline void Vertex(float _x, float _y, float _z, Color _color) { Vertex(Vec3(_x, _y, _z), _color); }
|
||||
inline void Vertex(float _x, float _y, float _z, float _size) { Vertex(Vec3(_x, _y, _z), _size); }
|
||||
inline void Vertex(float _x, float _y, float _z, float _size, Color _color) { Vertex(Vec3(_x, _y, _z), _size, _color); }
|
||||
|
||||
inline void PushDrawState() { Context& ctx = GetContext(); ctx.pushColor(ctx.getColor()); ctx.pushAlpha(ctx.getAlpha()); ctx.pushSize(ctx.getSize()); ctx.pushEnableSorting(ctx.getEnableSorting()); }
|
||||
inline void PopDrawState() { Context& ctx = GetContext(); ctx.popColor(); ctx.popAlpha(); ctx.popSize(); ctx.popEnableSorting(); }
|
||||
|
||||
inline void PushColor() { GetContext().pushColor(GetContext().getColor()); }
|
||||
inline void PushColor(Color _color) { GetContext().pushColor(_color); }
|
||||
inline void PopColor() { GetContext().popColor(); }
|
||||
inline void SetColor(Color _color) { GetContext().setColor(_color); }
|
||||
inline void SetColor(float _r, float _g, float _b, float _a) { GetContext().setColor(Color(_r, _g, _b, _a)); }
|
||||
inline Color GetColor() { return GetContext().getColor(); }
|
||||
|
||||
inline void PushAlpha() { GetContext().pushAlpha(GetContext().getAlpha()); }
|
||||
inline void PushAlpha(float _alpha) { GetContext().pushAlpha(_alpha); }
|
||||
inline void PopAlpha() { GetContext().popAlpha(); }
|
||||
inline void SetAlpha(float _alpha) { GetContext().setAlpha(_alpha); }
|
||||
inline float GetAlpha() { return GetContext().getAlpha(); }
|
||||
|
||||
inline void PushSize() { GetContext().pushSize(GetContext().getAlpha()); }
|
||||
inline void PushSize(float _size) { GetContext().pushSize(_size); }
|
||||
inline void PopSize() { GetContext().popSize(); }
|
||||
inline void SetSize(float _size) { GetContext().setSize(_size); }
|
||||
inline float GetSize() { return GetContext().getSize(); }
|
||||
|
||||
inline void PushEnableSorting() { GetContext().pushEnableSorting(GetContext().getEnableSorting()); }
|
||||
inline void PushEnableSorting(bool _enable) { GetContext().pushEnableSorting(_enable); }
|
||||
inline void PopEnableSorting() { GetContext().popEnableSorting(); }
|
||||
inline void EnableSorting(bool _enable) { GetContext().setEnableSorting(_enable); }
|
||||
|
||||
inline void PushMatrix() { GetContext().pushMatrix(GetContext().getMatrix()); }
|
||||
inline void PushMatrix(const Mat4& _mat4) { GetContext().pushMatrix(_mat4); }
|
||||
inline void PopMatrix() { GetContext().popMatrix(); }
|
||||
inline void SetMatrix(const Mat4& _mat4) { GetContext().setMatrix(_mat4); }
|
||||
inline void SetIdentity() { GetContext().setMatrix(Mat4(1.0f)); }
|
||||
|
||||
inline void PushId() { GetContext().pushId(GetContext().getId()); }
|
||||
inline void PushId(Id _id) { GetContext().pushId(_id); }
|
||||
inline void PushId(const char* _str) { GetContext().pushId(MakeId(_str)); }
|
||||
inline void PushId(const void* _ptr) { GetContext().pushId(MakeId(_ptr)); }
|
||||
inline void PushId(int _i) { GetContext().pushId(MakeId(_i)); }
|
||||
inline void PopId() { GetContext().popId(); }
|
||||
inline Id GetId() { return GetContext().getId(); }
|
||||
|
||||
inline void PushLayerId() { GetContext().pushLayerId(GetContext().getLayerId()); }
|
||||
inline void PushLayerId(Id _layer) { GetContext().pushLayerId(_layer); }
|
||||
inline void PushLayerId(const char* _str) { PushLayerId(MakeId(_str)); }
|
||||
inline void PopLayerId() { GetContext().popLayerId(); }
|
||||
inline Id GetLayerId() { return GetContext().getLayerId(); }
|
||||
|
||||
inline bool GizmoTranslation(const char* _id, float _translation_[3], bool _local) { return GizmoTranslation(MakeId(_id), _translation_, _local); }
|
||||
inline bool GizmoRotation(const char* _id, float _rotation_[3*3], bool _local) { return GizmoRotation(MakeId(_id), _rotation_, _local);}
|
||||
inline bool GizmoScale(const char* _id, float _scale_[3]) { return GizmoScale(MakeId(_id), _scale_); }
|
||||
inline bool Gizmo(const char* _id, float _translation_[3], float _rotation_[3*3], float _scale_[3]) { return Gizmo(MakeId(_id), _translation_, _rotation_, _scale_); }
|
||||
inline bool Gizmo(const char* _id, float _transform_[4*4]) { return Gizmo(MakeId(_id), _transform_); }
|
||||
inline Id GetActiveId() { return GetContext().m_appActiveId;}
|
||||
inline Id GetHotId() { return GetContext().m_appHotId; }
|
||||
|
||||
inline bool IsVisible(const Vec3& _origin, float _radius) { return GetContext().isVisible(_origin, _radius); }
|
||||
inline bool IsVisible(const Vec3& _min, const Vec3& _max) { return GetContext().isVisible(_min, _max);}
|
||||
|
||||
inline Context& GetContext() { return *internal::g_CurrentContext; }
|
||||
inline void SetContext(Context& _ctx) { internal::g_CurrentContext = &_ctx; }
|
||||
inline void MergeContexts(Context& _dst_, const Context& _src) { _dst_.merge(_src); }
|
||||
|
||||
} // namespac Im3d
|
44
code/im3d/im3d_config.h
Normal file
44
code/im3d/im3d_config.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
// User-defined assertion handler (default is cassert assert()).
|
||||
#include <assert.h>
|
||||
#define IM3D_ASSERT(e) assert(e)
|
||||
|
||||
// User-defined malloc/free. Define both or neither (default is cstdlib malloc()/free()).
|
||||
//#define IM3D_MALLOC(size) malloc(size)
|
||||
//#define IM3D_FREE(ptr) free(ptr)
|
||||
|
||||
// User-defined API declaration (e.g. __declspec(dllexport)).
|
||||
//#define IM3D_API
|
||||
|
||||
// Use a thread-local context pointer.
|
||||
//#define IM3D_THREAD_LOCAL_CONTEXT_PTR 1
|
||||
|
||||
// Use row-major internal matrix layout.
|
||||
//#define IM3D_MATRIX_ROW_MAJOR 1
|
||||
|
||||
// Force vertex data alignment (default is 4 bytes).
|
||||
//#define IM3D_VERTEX_ALIGNMENT 4
|
||||
|
||||
// Enable internal culling for primitives (everything drawn between Begin*()/End()). The application must set a culling frustum via AppData.
|
||||
//#define IM3D_CULL_PRIMITIVES 1
|
||||
|
||||
// Enable internal culling for gizmos. The application must set a culling frustum via AppData.
|
||||
//#define IM3D_CULL_GIZMOS 1
|
||||
|
||||
// Conversion to/from application math types.
|
||||
//#define IM3D_VEC2_APP
|
||||
// Vec2(const glm::vec2& _v) { x = _v.x; y = _v.y; }
|
||||
// operator glm::vec2() const { return glm::vec2(x, y); }
|
||||
//#define IM3D_VEC3_APP
|
||||
// Vec3(const glm::vec3& _v) { x = _v.x; y = _v.y; z = _v.z; }
|
||||
// operator glm::vec3() const { return glm::vec3(x, y, z); }
|
||||
//#define IM3D_VEC4_APP
|
||||
// Vec4(const glm::vec4& _v) { x = _v.x; y = _v.y; z = _v.z; w = _v.w; }
|
||||
// operator glm::vec4() const { return glm::vec4(x, y, z, w); }
|
||||
//#define IM3D_MAT3_APP
|
||||
// Mat3(const glm::mat3& _m) { for (int i = 0; i < 9; ++i) m[i] = *(&(_m[0][0]) + i); }
|
||||
// operator glm::mat3() const { glm::mat3 ret; for (int i = 0; i < 9; ++i) *(&(ret[0][0]) + i) = m[i]; return ret; }
|
||||
//#define IM3D_MAT4_APP
|
||||
// Mat4(const glm::mat4& _m) { for (int i = 0; i < 16; ++i) m[i] = *(&(_m[0][0]) + i); }
|
||||
// operator glm::mat4() const { glm::mat4 ret; for (int i = 0; i < 16; ++i) *(&(ret[0][0]) + i) = m[i]; return ret; }
|
306
code/im3d/im3d_math.h
Normal file
306
code/im3d/im3d_math.h
Normal file
|
@ -0,0 +1,306 @@
|
|||
#pragma once
|
||||
|
||||
// im3d_math.h is optional - include only if you want to use the Im3d math types directly
|
||||
|
||||
#include "im3d.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace Im3d {
|
||||
|
||||
// Vec2
|
||||
inline Vec2 operator+(const Vec2& _lhs, const Vec2& _rhs) { return Vec2(_lhs.x + _rhs.x, _lhs.y + _rhs.y); }
|
||||
inline Vec2 operator-(const Vec2& _lhs, const Vec2& _rhs) { return Vec2(_lhs.x - _rhs.x, _lhs.y - _rhs.y); }
|
||||
inline Vec2 operator*(const Vec2& _lhs, const Vec2& _rhs) { return Vec2(_lhs.x * _rhs.x, _lhs.y * _rhs.y); }
|
||||
inline Vec2 operator/(const Vec2& _lhs, const Vec2& _rhs) { return Vec2(_lhs.x / _rhs.x, _lhs.y / _rhs.y); }
|
||||
inline Vec2 operator*(const Vec2& _lhs, float _rhs) { return Vec2(_lhs.x * _rhs, _lhs.y * _rhs); }
|
||||
inline Vec2 operator/(const Vec2& _lhs, float _rhs) { return Vec2(_lhs.x / _rhs, _lhs.y / _rhs); }
|
||||
inline Vec2 operator-(const Vec2& _v) { return Vec2(-_v.x, -_v.y); }
|
||||
inline float Dot(const Vec2& _lhs, const Vec2& _rhs) { return _lhs.x * _rhs.x + _lhs.y * _rhs.y; }
|
||||
inline float Length(const Vec2& _v) { return sqrtf(Dot(_v, _v)); }
|
||||
inline float Length2(const Vec2& _v) { return Dot(_v, _v); }
|
||||
inline Vec2 Abs(const Vec2& _v) { return Vec2(fabs(_v.x), fabs(_v.y)); }
|
||||
inline Vec2 Normalize(const Vec2& _v) { return _v / Length(_v); }
|
||||
|
||||
// Vec3
|
||||
inline Vec3 operator+(const Vec3& _lhs, const Vec3& _rhs) { return Vec3(_lhs.x + _rhs.x, _lhs.y + _rhs.y, _lhs.z + _rhs.z); }
|
||||
inline Vec3 operator-(const Vec3& _lhs, const Vec3& _rhs) { return Vec3(_lhs.x - _rhs.x, _lhs.y - _rhs.y, _lhs.z - _rhs.z); }
|
||||
inline Vec3 operator*(const Vec3& _lhs, const Vec3& _rhs) { return Vec3(_lhs.x * _rhs.x, _lhs.y * _rhs.y, _lhs.z * _rhs.z); }
|
||||
inline Vec3 operator/(const Vec3& _lhs, const Vec3& _rhs) { return Vec3(_lhs.x / _rhs.x, _lhs.y / _rhs.y, _lhs.z / _rhs.z); }
|
||||
inline Vec3 operator*(const Vec3& _lhs, float _rhs) { return Vec3(_lhs.x * _rhs, _lhs.y * _rhs, _lhs.z * _rhs); }
|
||||
inline Vec3 operator/(const Vec3& _lhs, float _rhs) { return Vec3(_lhs.x / _rhs, _lhs.y / _rhs, _lhs.z / _rhs); }
|
||||
inline Vec3 operator-(const Vec3& _v) { return Vec3(-_v.x, -_v.y, -_v.z); }
|
||||
inline float Dot(const Vec3& _lhs, const Vec3& _rhs) { return _lhs.x * _rhs.x + _lhs.y * _rhs.y + _lhs.z * _rhs.z; }
|
||||
inline float Length(const Vec3& _v) { return sqrtf(Dot(_v, _v)); }
|
||||
inline float Length2(const Vec3& _v) { return Dot(_v, _v); }
|
||||
inline Vec3 Abs(const Vec3& _v) { return Vec3(fabs(_v.x), fabs(_v.y), fabs(_v.z)); }
|
||||
inline Vec3 Normalize(const Vec3& _v) { return _v / Length(_v); }
|
||||
inline Vec3 Cross(const Vec3& _a, const Vec3& _b)
|
||||
{
|
||||
return Vec3(
|
||||
_a.y * _b.z - _b.y * _a.z,
|
||||
_a.z * _b.x - _b.z * _a.x,
|
||||
_a.x * _b.y - _b.x * _a.y
|
||||
);
|
||||
}
|
||||
|
||||
// Vec4
|
||||
inline Vec4 operator+(const Vec4& _lhs, const Vec4& _rhs) { return Vec4(_lhs.x + _rhs.x, _lhs.y + _rhs.y, _lhs.z + _rhs.z, _lhs.w + _rhs.w); }
|
||||
inline Vec4 operator-(const Vec4& _lhs, const Vec4& _rhs) { return Vec4(_lhs.x - _rhs.x, _lhs.y - _rhs.y, _lhs.z - _rhs.z, _lhs.w - _rhs.w); }
|
||||
inline Vec4 operator*(const Vec4& _lhs, const Vec4& _rhs) { return Vec4(_lhs.x * _rhs.x, _lhs.y * _rhs.y, _lhs.z * _rhs.z, _lhs.w * _rhs.w); }
|
||||
inline Vec4 operator/(const Vec4& _lhs, const Vec4& _rhs) { return Vec4(_lhs.x / _rhs.x, _lhs.y / _rhs.y, _lhs.z / _rhs.z, _lhs.w / _rhs.w); }
|
||||
inline Vec4 operator*(const Vec4& _lhs, float _rhs) { return Vec4(_lhs.x * _rhs, _lhs.y * _rhs, _lhs.z * _rhs, _lhs.w * _rhs); }
|
||||
inline Vec4 operator/(const Vec4& _lhs, float _rhs) { return Vec4(_lhs.x / _rhs, _lhs.y / _rhs, _lhs.z / _rhs, _lhs.w / _rhs); }
|
||||
inline Vec4 operator-(const Vec4& _v) { return Vec4(-_v.x, -_v.y, -_v.z, -_v.w); }
|
||||
inline float Dot(const Vec4& _lhs, const Vec4& _rhs) { return _lhs.x * _rhs.x + _lhs.y * _rhs.y + _lhs.z * _rhs.z + _lhs.w * _rhs.w; }
|
||||
inline float Length(const Vec4& _v) { return sqrtf(Dot(_v, _v)); }
|
||||
inline float Length2(const Vec4& _v) { return Dot(_v, _v); }
|
||||
inline Vec4 Abs(const Vec4& _v) { return Vec4(fabs(_v.x), fabs(_v.y), fabs(_v.z), fabs(_v.w)); }
|
||||
inline Vec4 Normalize(const Vec4& _v) { return _v / Length(_v); }
|
||||
|
||||
// Mat3
|
||||
inline Mat3 operator*(const Mat3& _lhs, const Mat3& _rhs)
|
||||
{
|
||||
Mat3 ret;
|
||||
ret(0, 0) = _lhs(0, 0) * _rhs(0, 0) + _lhs(0, 1) * _rhs(1, 0) + _lhs(0, 2) * _rhs(2, 0);
|
||||
ret(0, 1) = _lhs(0, 0) * _rhs(0, 1) + _lhs(0, 1) * _rhs(1, 1) + _lhs(0, 2) * _rhs(2, 1);
|
||||
ret(0, 2) = _lhs(0, 0) * _rhs(0, 2) + _lhs(0, 1) * _rhs(1, 2) + _lhs(0, 2) * _rhs(2, 2);
|
||||
ret(1, 0) = _lhs(1, 0) * _rhs(0, 0) + _lhs(1, 1) * _rhs(1, 0) + _lhs(1, 2) * _rhs(2, 0);
|
||||
ret(1, 1) = _lhs(1, 0) * _rhs(0, 1) + _lhs(1, 1) * _rhs(1, 1) + _lhs(1, 2) * _rhs(2, 1);
|
||||
ret(1, 2) = _lhs(1, 0) * _rhs(0, 2) + _lhs(1, 1) * _rhs(1, 2) + _lhs(1, 2) * _rhs(2, 2);
|
||||
ret(2, 0) = _lhs(2, 0) * _rhs(0, 0) + _lhs(2, 1) * _rhs(1, 0) + _lhs(2, 2) * _rhs(2, 0);
|
||||
ret(2, 1) = _lhs(2, 0) * _rhs(0, 1) + _lhs(2, 1) * _rhs(1, 1) + _lhs(2, 2) * _rhs(2, 1);
|
||||
ret(2, 2) = _lhs(2, 0) * _rhs(0, 2) + _lhs(2, 1) * _rhs(1, 2) + _lhs(2, 2) * _rhs(2, 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
inline Vec3 operator*(const Mat3& _m, const Vec3& _v)
|
||||
{
|
||||
return Vec3(
|
||||
_m(0, 0) * _v.x + _m(0, 1) * _v.y + _m(0, 2) * _v.z,
|
||||
_m(1, 0) * _v.x + _m(1, 1) * _v.y + _m(1, 2) * _v.z,
|
||||
_m(2, 0) * _v.x + _m(2, 1) * _v.y + _m(2, 2) * _v.z
|
||||
);
|
||||
}
|
||||
inline Vec4 operator*(const Mat3& _m, const Vec4& _v)
|
||||
{
|
||||
return Vec4(
|
||||
_m(0, 0) * _v.x + _m(0, 1) * _v.y + _m(0, 2) * _v.z,
|
||||
_m(1, 0) * _v.x + _m(1, 1) * _v.y + _m(1, 2) * _v.z,
|
||||
_m(2, 0) * _v.x + _m(2, 1) * _v.y + _m(2, 2) * _v.z,
|
||||
_v.w
|
||||
);
|
||||
}
|
||||
Mat3 Transpose(const Mat3& _m);
|
||||
Vec3 ToEulerXYZ(const Mat3& _m);
|
||||
Mat3 FromEulerXYZ(Vec3& _xyz);
|
||||
Mat3 Rotation(const Vec3& _axis, float _rads); // _axis must be unit length
|
||||
Mat3 Scale(const Vec3& _s);
|
||||
|
||||
// Mat4
|
||||
inline Mat4 operator*(const Mat4& _lhs, const Mat4& _rhs)
|
||||
{
|
||||
Mat4 ret;
|
||||
ret(0, 0) = _lhs(0, 0) * _rhs(0, 0) + _lhs(0, 1) * _rhs(1, 0) + _lhs(0, 2) * _rhs(2, 0) + _lhs(0, 3) * _rhs(3, 0);
|
||||
ret(0, 1) = _lhs(0, 0) * _rhs(0, 1) + _lhs(0, 1) * _rhs(1, 1) + _lhs(0, 2) * _rhs(2, 1) + _lhs(0, 3) * _rhs(3, 1);
|
||||
ret(0, 2) = _lhs(0, 0) * _rhs(0, 2) + _lhs(0, 1) * _rhs(1, 2) + _lhs(0, 2) * _rhs(2, 2) + _lhs(0, 3) * _rhs(3, 2);
|
||||
ret(0, 3) = _lhs(0, 0) * _rhs(0, 3) + _lhs(0, 1) * _rhs(1, 3) + _lhs(0, 2) * _rhs(2, 3) + _lhs(0, 3) * _rhs(3, 3);
|
||||
ret(1, 0) = _lhs(1, 0) * _rhs(0, 0) + _lhs(1, 1) * _rhs(1, 0) + _lhs(1, 2) * _rhs(2, 0) + _lhs(1, 3) * _rhs(3, 0);
|
||||
ret(1, 1) = _lhs(1, 0) * _rhs(0, 1) + _lhs(1, 1) * _rhs(1, 1) + _lhs(1, 2) * _rhs(2, 1) + _lhs(1, 3) * _rhs(3, 1);
|
||||
ret(1, 2) = _lhs(1, 0) * _rhs(0, 2) + _lhs(1, 1) * _rhs(1, 2) + _lhs(1, 2) * _rhs(2, 2) + _lhs(1, 3) * _rhs(3, 2);
|
||||
ret(1, 3) = _lhs(1, 0) * _rhs(0, 3) + _lhs(1, 1) * _rhs(1, 3) + _lhs(1, 2) * _rhs(2, 3) + _lhs(1, 3) * _rhs(3, 3);
|
||||
ret(2, 0) = _lhs(2, 0) * _rhs(0, 0) + _lhs(2, 1) * _rhs(1, 0) + _lhs(2, 2) * _rhs(2, 0) + _lhs(2, 3) * _rhs(3, 0);
|
||||
ret(2, 1) = _lhs(2, 0) * _rhs(0, 1) + _lhs(2, 1) * _rhs(1, 1) + _lhs(2, 2) * _rhs(2, 1) + _lhs(2, 3) * _rhs(3, 1);
|
||||
ret(2, 2) = _lhs(2, 0) * _rhs(0, 2) + _lhs(2, 1) * _rhs(1, 2) + _lhs(2, 2) * _rhs(2, 2) + _lhs(2, 3) * _rhs(3, 2);
|
||||
ret(2, 3) = _lhs(2, 0) * _rhs(0, 3) + _lhs(2, 1) * _rhs(1, 3) + _lhs(2, 2) * _rhs(2, 3) + _lhs(2, 3) * _rhs(3, 3);
|
||||
ret(3, 0) = _lhs(3, 0) * _rhs(0, 0) + _lhs(3, 1) * _rhs(1, 0) + _lhs(3, 2) * _rhs(2, 0) + _lhs(3, 3) * _rhs(3, 0);
|
||||
ret(3, 1) = _lhs(3, 0) * _rhs(0, 1) + _lhs(3, 1) * _rhs(1, 1) + _lhs(3, 2) * _rhs(2, 1) + _lhs(3, 3) * _rhs(3, 1);
|
||||
ret(3, 2) = _lhs(3, 0) * _rhs(0, 2) + _lhs(3, 1) * _rhs(1, 2) + _lhs(3, 2) * _rhs(2, 2) + _lhs(3, 3) * _rhs(3, 2);
|
||||
ret(3, 3) = _lhs(3, 0) * _rhs(0, 3) + _lhs(3, 1) * _rhs(1, 3) + _lhs(3, 2) * _rhs(2, 3) + _lhs(3, 3) * _rhs(3, 3);
|
||||
|
||||
return ret;
|
||||
}
|
||||
inline Vec3 operator*(const Mat4& _m, const Vec3& _pos)
|
||||
{
|
||||
return Vec3(
|
||||
_m(0, 0) * _pos.x + _m(0, 1) * _pos.y + _m(0, 2) * _pos.z + _m(0, 3),
|
||||
_m(1, 0) * _pos.x + _m(1, 1) * _pos.y + _m(1, 2) * _pos.z + _m(1, 3),
|
||||
_m(2, 0) * _pos.x + _m(2, 1) * _pos.y + _m(2, 2) * _pos.z + _m(2, 3)
|
||||
);
|
||||
}
|
||||
inline Vec4 operator*(const Mat4& _m, const Vec4& _v)
|
||||
{
|
||||
return Vec4(
|
||||
_m(0, 0) * _v.x + _m(0, 1) * _v.y + _m(0, 2) * _v.z + _m(0, 3) * _v.w,
|
||||
_m(1, 0) * _v.x + _m(1, 1) * _v.y + _m(1, 2) * _v.z + _m(1, 3) * _v.w,
|
||||
_m(2, 0) * _v.x + _m(2, 1) * _v.y + _m(2, 2) * _v.z + _m(2, 3) * _v.w,
|
||||
_m(3, 0) * _v.x + _m(3, 1) * _v.y + _m(3, 2) * _v.z + _m(3, 3) * _v.w
|
||||
);
|
||||
}
|
||||
Mat4 Inverse(const Mat4& _m);
|
||||
Mat4 Transpose(const Mat4& _m);
|
||||
Mat4 Translation(const Vec3& _t);
|
||||
Mat4 AlignZ(const Vec3& _axis, const Vec3& _up = Vec3(0.0f, 1.0f, 0.0f)); // generate an orthonormal bases with +z as _axis, which must be unit length
|
||||
Mat4 LookAt(const Vec3& _from, const Vec3& _to, const Vec3& _up = Vec3(0.0f, 1.0f, 0.0f)); // align _z with (_to - _from), set _from as translation
|
||||
|
||||
struct Line
|
||||
{
|
||||
Vec3 m_origin;
|
||||
Vec3 m_direction; // unit length
|
||||
|
||||
Line() {}
|
||||
Line(const Vec3& _origin, const Vec3& _direction);
|
||||
};
|
||||
struct Ray
|
||||
{
|
||||
Vec3 m_origin;
|
||||
Vec3 m_direction; // unit length
|
||||
|
||||
Ray() {}
|
||||
Ray(const Vec3& _origin, const Vec3& _direction);
|
||||
};
|
||||
struct LineSegment
|
||||
{
|
||||
Vec3 m_start;
|
||||
Vec3 m_end;
|
||||
|
||||
LineSegment() {}
|
||||
LineSegment(const Vec3& _start, const Vec3& _end);
|
||||
};
|
||||
struct Sphere
|
||||
{
|
||||
Vec3 m_origin;
|
||||
float m_radius;
|
||||
|
||||
Sphere() {}
|
||||
Sphere(const Vec3& _origin, float _radius);
|
||||
};
|
||||
struct Plane
|
||||
{
|
||||
Vec3 m_normal;
|
||||
float m_offset;
|
||||
|
||||
Plane() {}
|
||||
Plane(const Vec3& _normal, float _offset);
|
||||
Plane(const Vec3& _normal, const Vec3& _origin);
|
||||
};
|
||||
struct Capsule
|
||||
{
|
||||
Vec3 m_start;
|
||||
Vec3 m_end;
|
||||
float m_radius;
|
||||
|
||||
Capsule() {}
|
||||
Capsule(const Vec3& _start, const Vec3& _end, float _radius);
|
||||
};
|
||||
|
||||
|
||||
// Ray-primitive intersections. Use Intersects() when you don't need t.
|
||||
bool Intersects(const Ray& _ray, const Plane& _plane );
|
||||
bool Intersect (const Ray& _ray, const Plane& _plane, float& t0_ );
|
||||
bool Intersects(const Ray& _ray, const Sphere& _sphere );
|
||||
bool Intersect (const Ray& _ray, const Sphere& _sphere, float& t0_, float& t1_);
|
||||
bool Intersects(const Ray& _ray, const Capsule& _capsule );
|
||||
bool Intersect (const Ray& _ray, const Capsule& _capsule, float& t0_, float& t1_);
|
||||
|
||||
// Find point t0_ along _line0 nearest to _line1 and t1_ along _line1 nearest to _line0.
|
||||
void Nearest(const Line& _line0, const Line& _line1, float& t0_, float& t1_);
|
||||
// Find point tr_ along _ray nearest to _line and tl_ along _line nearest to _ray.
|
||||
void Nearest(const Ray& _ray, const Line& _line, float& tr_, float& tl_);
|
||||
// Find point tr_ along _ray nearest to _segment, return point on segment nearest to _ray.
|
||||
Vec3 Nearest(const Ray& _ray, const LineSegment& _segment, float& tr_);
|
||||
|
||||
float Distance2(const Ray& _ray, const LineSegment& _segment);
|
||||
|
||||
inline float Distance(const Vec4& _plane, const Vec3& _point){ return _plane.x * _point.x + _plane.y * _point.y + _plane.z * _point.z - _plane.w; }
|
||||
|
||||
constexpr float Pi = 3.14159265359f;
|
||||
constexpr float TwoPi = 2.0f * Pi;
|
||||
constexpr float HalfPi = 0.5f * Pi;
|
||||
|
||||
inline float Radians(float _degrees) { return _degrees * (Pi / 180.0f); }
|
||||
inline float Degrees(float _radians) { return _radians * (180.0f / Pi); }
|
||||
|
||||
namespace internal {
|
||||
|
||||
struct ScalarT {};
|
||||
struct FloatT: public ScalarT {};
|
||||
struct IntT: public ScalarT {};
|
||||
struct CompositeT {};
|
||||
struct VecT: public CompositeT {};
|
||||
struct MatT: public CompositeT {};
|
||||
template <typename T>
|
||||
struct TypeTraits { typedef typename T::Type Type; enum { kSize = T::kSize }; };
|
||||
template<> struct TypeTraits<int> { typedef IntT Type; enum { kSize = 1 }; };
|
||||
template<> struct TypeTraits<float> { typedef FloatT Type; enum { kSize = 1 }; };
|
||||
template<> struct TypeTraits<Vec2> { typedef VecT Type; enum { kSize = 2 }; };
|
||||
template<> struct TypeTraits<Vec3> { typedef VecT Type; enum { kSize = 3 }; };
|
||||
template<> struct TypeTraits<Vec4> { typedef VecT Type; enum { kSize = 4 }; };
|
||||
template<> struct TypeTraits<Mat4> { typedef MatT Type; enum { kSize = 16 }; };
|
||||
|
||||
template <typename T>
|
||||
inline bool _AllLess(const T& _a, const T& _b, ScalarT)
|
||||
{
|
||||
return _a < _b;
|
||||
}
|
||||
template <typename T>
|
||||
inline bool _AllLess(const T& _a, const T& _b, CompositeT)
|
||||
{
|
||||
for (int i = 0, n = TypeTraits<T>::kSize; i < n; ++i)
|
||||
{
|
||||
if (_a[i] > _b[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T _Max(const T& _a, const T& _b, ScalarT)
|
||||
{
|
||||
return _a < _b ? _b : _a;
|
||||
}
|
||||
template <typename T>
|
||||
inline T _Max(const T& _a, const T& _b, CompositeT)
|
||||
{
|
||||
T ret;
|
||||
for (int i = 0, n = TypeTraits<T>::kSize; i < n; ++i) {
|
||||
ret[i] = _Max(_a[i], _b[i], ScalarT());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T _Min(const T& _a, const T& _b, ScalarT)
|
||||
{
|
||||
return _a < _b ? _a : _b;
|
||||
}
|
||||
template <typename T>
|
||||
inline T _Min(const T& _a, const T& _b, CompositeT)
|
||||
{
|
||||
T ret;
|
||||
for (int i = 0, n = TypeTraits<T>::kSize; i < n; ++i)
|
||||
{
|
||||
ret[i] = _Min(_a[i], _b[i], ScalarT());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline bool AllLess(const T& _a, const T& _b) { return internal::_AllLess(_a, _b, typename internal::TypeTraits<T>::Type()); }
|
||||
|
||||
template <typename T>
|
||||
inline T Max(T _a, T _b) { return internal::_Max(_a, _b, typename internal::TypeTraits<T>::Type()); }
|
||||
template <typename T>
|
||||
inline T Min(T _a, T _b) { return internal::_Min(_a, _b, typename internal::TypeTraits<T>::Type()); }
|
||||
template <typename T>
|
||||
inline T Clamp(T _a, T _min, T _max) { return Max(Min(_a, _max), _min); }
|
||||
|
||||
// Remap _x in [_start,_end] to [0,1].
|
||||
inline float Remap(float _x, float _start, float _end) { return Clamp(_x * (1.0f / (_end - _start)) + (-_start / (_end - _start)), 0.0f, 1.0f); }
|
||||
|
||||
} // namespace Im3d
|
|
@ -478,6 +478,7 @@ struct NanoVDBManager
|
|||
|
||||
void Init();
|
||||
void DrawGUI();
|
||||
void DrawIm3d();
|
||||
void BeforeFrame();
|
||||
bool AddSequence(const VDBSequenceDesc& desc);
|
||||
void MakeWorldToIndexMatrix(matrix3x3_t matrix, const Instance& instance);
|
||||
|
@ -564,6 +565,7 @@ struct NanoVDBManager
|
|||
bool ambientIncreasedCoverage = true;
|
||||
bool previewMode = false;
|
||||
float emissiveScatterScale = 0.5f;
|
||||
int activeInstanceIndex = -1;
|
||||
};
|
||||
|
||||
struct ParticleSystem
|
||||
|
@ -595,6 +597,7 @@ struct VolumetricLight
|
|||
void DrawEnd();
|
||||
void DrawDebug();
|
||||
void DrawGUI();
|
||||
void DrawIm3d();
|
||||
bool WantRTASUpdate(const trRefdef_t& scene);
|
||||
bool ShouldDraw();
|
||||
bool ShouldDrawDebug();
|
||||
|
@ -607,8 +610,8 @@ struct VolumetricLight
|
|||
{
|
||||
vec3_t scatterColor;
|
||||
vec3_t emissiveColor;
|
||||
vec3_t boxMin;
|
||||
vec3_t boxMax;
|
||||
vec3_t boxCenter;
|
||||
vec3_t boxSize;
|
||||
float extinction;
|
||||
float albedo; // thin fog: 0.3 to 0.5, thick fog: 0.6 to 0.9
|
||||
float emissive;
|
||||
|
@ -708,6 +711,7 @@ struct VolumetricLight
|
|||
int extinctionResolution = 128;
|
||||
int sunShadowResolution = 128;
|
||||
int pointShadowResolution = 64;
|
||||
int activeFogIndex = -1; // tab GUI index
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
@ -854,6 +858,7 @@ struct CRP : IRenderPipeline
|
|||
UI ui;
|
||||
MipMapGenerator mipMapGen;
|
||||
ImGUI imgui;
|
||||
Im3D im3d;
|
||||
Nuklear nuklear;
|
||||
Prepass prepass;
|
||||
WorldOpaque opaque;
|
||||
|
|
|
@ -34,6 +34,9 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|||
#include "compshaders/crp/mip_2.h"
|
||||
#include "compshaders/crp/mip_3.h"
|
||||
#include "compshaders/crp/depth_pyramid.h"
|
||||
#include "compshaders/crp/im3d_points.h"
|
||||
#include "compshaders/crp/im3d_lines.h"
|
||||
#include "compshaders/crp/im3d_triangles.h"
|
||||
|
||||
|
||||
struct SceneViewConst
|
||||
|
@ -575,9 +578,18 @@ void CRP::Init()
|
|||
sceneViewBuffer = CreateBuffer(desc);
|
||||
}
|
||||
|
||||
ShaderByteCode im3dShaders[Im3D::Shader::Count];
|
||||
im3dShaders[Im3D::Shader::PointVS] = ShaderByteCode(g_im3d_points_vs);
|
||||
im3dShaders[Im3D::Shader::PointPS] = ShaderByteCode(g_im3d_points_ps);
|
||||
im3dShaders[Im3D::Shader::LineVS] = ShaderByteCode(g_im3d_lines_vs);
|
||||
im3dShaders[Im3D::Shader::LinePS] = ShaderByteCode(g_im3d_lines_ps);
|
||||
im3dShaders[Im3D::Shader::TriangleVS] = ShaderByteCode(g_im3d_triangles_vs);
|
||||
im3dShaders[Im3D::Shader::TrianglePS] = ShaderByteCode(g_im3d_triangles_ps);
|
||||
|
||||
raytracing.Init();
|
||||
ui.Init(true, ShaderByteCode(g_ui_vs), ShaderByteCode(g_ui_ps), renderTargetFormat, RHI_MAKE_NULL_HANDLE(), NULL);
|
||||
imgui.Init(true, ShaderByteCode(g_imgui_vs), ShaderByteCode(g_imgui_ps), renderTargetFormat, RHI_MAKE_NULL_HANDLE(), NULL);
|
||||
im3d.Init(true, im3dShaders, renderTargetFormat);
|
||||
nuklear.Init(true, ShaderByteCode(g_nuklear_vs), ShaderByteCode(g_nuklear_ps), renderTargetFormat, RHI_MAKE_NULL_HANDLE(), NULL);
|
||||
mipMapGen.Init(true, ShaderByteCode(g_mip_1_cs), ShaderByteCode(g_mip_2_cs), ShaderByteCode(g_mip_3_cs));
|
||||
prepass.Init();
|
||||
|
@ -636,6 +648,7 @@ void CRP::BeginFrame()
|
|||
raytracing.BeginFrame(rtasUpdate); // does BLAS/TLAS builds
|
||||
ui.BeginFrame();
|
||||
nuklear.BeginFrame();
|
||||
im3d.BeginFrame();
|
||||
|
||||
CmdBeginBarrier();
|
||||
CmdTextureBarrier(renderTarget, ResourceStates::RenderTargetBit);
|
||||
|
@ -673,6 +686,7 @@ void CRP::EndFrame()
|
|||
sunlightEditor.DrawGUI();
|
||||
volumetricLight.DrawGUI();
|
||||
vdbManager.DrawGUI();
|
||||
im3d.DrawGUI();
|
||||
imgui.Draw(renderTarget);
|
||||
toneMap.DrawToneMap();
|
||||
magnifier.Draw();
|
||||
|
@ -919,6 +933,9 @@ void CRP::DrawSceneView3D(const drawSceneViewCommand_t& cmd)
|
|||
volumetricLight.DrawDebug();
|
||||
transp.Draw(cmd);
|
||||
transpResolve.Draw(cmd);
|
||||
vdbManager.DrawIm3d();
|
||||
volumetricLight.DrawIm3d();
|
||||
im3d.Draw(cmd, renderTarget, depthTexture); // draw our debug stuff in front of all transparencies
|
||||
}
|
||||
|
||||
void CRP::DrawSceneView(const drawSceneViewCommand_t& cmd)
|
||||
|
|
|
@ -23,6 +23,7 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
#include "crp_local.h"
|
||||
#include "../client/cl_imgui.h"
|
||||
#include "../im3d/im3d.h"
|
||||
|
||||
#define NANOVDB_MAGIC_NUMBER 0x304244566F6E614Eul // "NanoVDB0"
|
||||
#define NANOVDB_MAGIC_GRID 0x314244566F6E614Eul // "NanoVDB1"
|
||||
|
@ -166,6 +167,49 @@ static void MultMatrix(matrix3x3_t m, const matrix3x3_t a, const matrix3x3_t b)
|
|||
m[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8];
|
||||
}
|
||||
|
||||
// similar to Python's math.isclose but the second value is the target for relative tolerance
|
||||
// i.e. abs(b) is used instead of max(abs(a), abs(b))
|
||||
static float IsCloseToTarget(float value, float target)
|
||||
{
|
||||
const float relTol = 1.e-6f; // relative tolerance
|
||||
const float absTol = 1.e-9f; // absolute tolerance
|
||||
|
||||
return fabsf(value - target) <= max(absTol, relTol * fabsf(target));
|
||||
}
|
||||
|
||||
// adapted from "Computing Euler angles from a rotation matrix" by Gregory G. Slabaugh
|
||||
static void AnglesRadFromMatrix(vec3_t anglesRad, const matrix3x3_t m)
|
||||
{
|
||||
#define R(x,y) m[y*3 + x]
|
||||
#define psi anglesRad[0]
|
||||
#define theta anglesRad[1]
|
||||
#define phi anglesRad[2]
|
||||
|
||||
phi = 0.0f;
|
||||
if(IsCloseToTarget(R(2, 0), -1.0f))
|
||||
{
|
||||
theta = M_PI / 2.0f;
|
||||
psi = atan2f(R(0, 1), R(0, 2));
|
||||
}
|
||||
else if(IsCloseToTarget(R(2, 0), 1.0f))
|
||||
{
|
||||
theta = -M_PI / 2.0f;
|
||||
psi = atan2f(-R(0, 1), -R(0, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
theta = -asinf(R(2, 0)); // theta2 = M_PI + asinf(R(2, 0));
|
||||
const float recCosTheta = 1.0f / cosf(theta);
|
||||
psi = atan2f(R(2, 1) * recCosTheta, R(2, 2) * recCosTheta);
|
||||
phi = atan2f(R(1, 0) * recCosTheta, R(0, 0) * recCosTheta);
|
||||
}
|
||||
|
||||
#undef R
|
||||
#undef psi
|
||||
#undef theta
|
||||
#undef phi
|
||||
}
|
||||
|
||||
static void FindGrids(FileGrid* grids, fileHandle_t fh, int byteCount, const VDBSequenceDesc& desc)
|
||||
{
|
||||
FileHeader fileHeader;
|
||||
|
@ -699,6 +743,7 @@ void NanoVDBManager::DrawGUI()
|
|||
{
|
||||
static const char* const sequencePopupTitle = "Add NanoVDB Sequence";
|
||||
|
||||
activeInstanceIndex = -1;
|
||||
if(!tr.worldMapLoaded)
|
||||
{
|
||||
return;
|
||||
|
@ -761,6 +806,8 @@ void NanoVDBManager::DrawGUI()
|
|||
{
|
||||
if(ImGui::BeginTabItem(va("#%d", i + 1)))
|
||||
{
|
||||
activeInstanceIndex = (int)i;
|
||||
|
||||
Instance& inst = instances[i];
|
||||
Sequence& seq = sequences[inst.sequenceIndex];
|
||||
|
||||
|
@ -843,6 +890,26 @@ void NanoVDBManager::DrawGUI()
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
void NanoVDBManager::DrawIm3d()
|
||||
{
|
||||
if((uint32_t)activeInstanceIndex < instances.count &&
|
||||
crp.im3d.ShouldDrawGizmos())
|
||||
{
|
||||
Instance& instance = instances[activeInstanceIndex];
|
||||
matrix3x3_t rotation, temp0, temp1, temp2;
|
||||
RotationMatrixX(temp0, -instance.anglesRad[0]);
|
||||
RotationMatrixY(temp1, -instance.anglesRad[1]);
|
||||
MultMatrix(temp2, temp0, temp1);
|
||||
RotationMatrixZ(temp0, -instance.anglesRad[2]);
|
||||
MultMatrix(rotation, temp2, temp0);
|
||||
const char* const id = va("VDB #%d", activeInstanceIndex);
|
||||
if(Im3d::Gizmo(id, instance.position, rotation, instance.scale))
|
||||
{
|
||||
AnglesRadFromMatrix(instance.anglesRad, rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NanoVDBManager::Purge()
|
||||
{
|
||||
// build sequence reference counts
|
||||
|
|
|
@ -23,6 +23,7 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
#include "crp_local.h"
|
||||
#include "../client/cl_imgui.h"
|
||||
#include "../im3d/im3d.h"
|
||||
#include "shaders/crp/scene_view.h.hlsli"
|
||||
#include "shaders/crp/light_grid.h.hlsli"
|
||||
#include "shaders/crp/vl_common.h.hlsli"
|
||||
|
@ -366,8 +367,11 @@ static void ConvertFog(FogVolume& dst, const VolumetricLight::Fog& src, const Vo
|
|||
}
|
||||
else
|
||||
{
|
||||
VectorCopy(src.boxMin, dst.boxMin);
|
||||
VectorCopy(src.boxMax, dst.boxMax);
|
||||
for(int a = 0; a < 3; a++)
|
||||
{
|
||||
dst.boxMin[a] = src.boxCenter[a] - 0.5f * src.boxSize[a];
|
||||
dst.boxMax[a] = src.boxCenter[a] + 0.5f * src.boxSize[a];
|
||||
}
|
||||
}
|
||||
dst.noiseMin = 1.0f;
|
||||
dst.noiseMax = src.noiseStrength;
|
||||
|
@ -769,8 +773,11 @@ void VolumetricLight::ProcessWorld(world_t& world)
|
|||
|
||||
Fog& fog = fogs[fogCount++];
|
||||
fog = {};
|
||||
VectorCopy(q3fog.bounds[0], fog.boxMin);
|
||||
VectorCopy(q3fog.bounds[1], fog.boxMax);
|
||||
for(int a = 0; a < 3; a++)
|
||||
{
|
||||
fog.boxCenter[a] = 0.5f * (q3fog.bounds[0][a] + q3fog.bounds[1][a]);
|
||||
fog.boxSize[a] = q3fog.bounds[1][a] - q3fog.bounds[0][a];
|
||||
}
|
||||
fog.extinction = extinction;
|
||||
fog.albedo = 0.75f;
|
||||
VectorCopy(q3fog.parms.color, fog.scatterColor);
|
||||
|
@ -1469,6 +1476,22 @@ void VolumetricLight::DrawEnd()
|
|||
jitterCounter++;
|
||||
}
|
||||
|
||||
void VolumetricLight::DrawIm3d()
|
||||
{
|
||||
if((uint32_t)activeFogIndex < fogCount &&
|
||||
crp.im3d.ShouldDrawGizmos())
|
||||
{
|
||||
Fog& fog = fogs[activeFogIndex];
|
||||
if(!fog.isGlobalFog)
|
||||
{
|
||||
const char* const id = va("Fog #%d", (int)activeFogIndex + 1);
|
||||
matrix3x3_t rotation;
|
||||
R_MakeIdentityMatrix3x3(rotation);
|
||||
Im3d::Gizmo(id, fog.boxCenter, rotation, fog.boxSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VolumetricLight::DrawDebug()
|
||||
{
|
||||
if(!ShouldDrawDebug())
|
||||
|
@ -1561,6 +1584,7 @@ void VolumetricLight::DrawDebug()
|
|||
|
||||
void VolumetricLight::DrawGUI()
|
||||
{
|
||||
activeFogIndex = -1;
|
||||
if(!tr.worldMapLoaded)
|
||||
{
|
||||
return;
|
||||
|
@ -1604,8 +1628,8 @@ void VolumetricLight::DrawGUI()
|
|||
fog.isGlobalFog = true;
|
||||
for(int a = 0; a < 3; a++)
|
||||
{
|
||||
fog.boxMin[a] = backEnd.refdef.vieworg[a] - fogSize;
|
||||
fog.boxMax[a] = backEnd.refdef.vieworg[a] + fogSize;
|
||||
VectorCopy(backEnd.refdef.vieworg, fog.boxCenter);
|
||||
VectorSet(fog.boxSize, fogSize, fogSize, fogSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1628,14 +1652,19 @@ void VolumetricLight::DrawGUI()
|
|||
{
|
||||
if(ImGui::BeginTabItem(va("#%d", i + 1)))
|
||||
{
|
||||
activeFogIndex = i;
|
||||
|
||||
Fog& fog = fogs[i];
|
||||
ImGui::Checkbox("Global fog", &fog.isGlobalFog);
|
||||
if(!fog.isGlobalFog)
|
||||
{
|
||||
for(int a = 0; a < 3; a++)
|
||||
{
|
||||
ImGui::SliderFloat(va("Box min %s", axisNames[a]), &fog.boxMin[a], mapBoxMin[a], mapBoxMax[a], "%g");
|
||||
ImGui::SliderFloat(va("Box max %s", axisNames[a]), &fog.boxMax[a], mapBoxMin[a], mapBoxMax[a], "%g");
|
||||
ImGui::SliderFloat(va("Box center %s", axisNames[a]), &fog.boxCenter[a], mapBoxMin[a], mapBoxMax[a], "%g");
|
||||
}
|
||||
for(int a = 0; a < 3; a++)
|
||||
{
|
||||
ImGui::SliderFloat(va("Box size %s", axisNames[a]), &fog.boxSize[a], 0.0f, mapBoxMax[a] - mapBoxMin[a], "%g");
|
||||
}
|
||||
}
|
||||
float opaqueDistance = ExtinctionToOpaqueDistance(fog.extinction);
|
||||
|
|
|
@ -339,6 +339,7 @@ struct GRP : IRenderPipeline
|
|||
World world;
|
||||
MipMapGenerator mipMapGen;
|
||||
ImGUI imgui;
|
||||
Im3D im3d;
|
||||
PostProcess post;
|
||||
SMAA smaa;
|
||||
Nuklear nuklear;
|
||||
|
|
|
@ -33,6 +33,9 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|||
#include "compshaders/grp/mip_1.h"
|
||||
#include "compshaders/grp/mip_2.h"
|
||||
#include "compshaders/grp/mip_3.h"
|
||||
#include "compshaders/grp/im3d_points.h"
|
||||
#include "compshaders/grp/im3d_lines.h"
|
||||
#include "compshaders/grp/im3d_triangles.h"
|
||||
|
||||
|
||||
GRP grp;
|
||||
|
@ -202,12 +205,21 @@ void GRP::Init()
|
|||
readbackRenderTarget = RHI::CreateTexture(desc);
|
||||
}
|
||||
|
||||
ShaderByteCode im3dShaders[Im3D::Shader::Count];
|
||||
im3dShaders[Im3D::Shader::PointVS] = ShaderByteCode(g_im3d_points_vs);
|
||||
im3dShaders[Im3D::Shader::PointPS] = ShaderByteCode(g_im3d_points_ps);
|
||||
im3dShaders[Im3D::Shader::LineVS] = ShaderByteCode(g_im3d_lines_vs);
|
||||
im3dShaders[Im3D::Shader::LinePS] = ShaderByteCode(g_im3d_lines_ps);
|
||||
im3dShaders[Im3D::Shader::TriangleVS] = ShaderByteCode(g_im3d_triangles_vs);
|
||||
im3dShaders[Im3D::Shader::TrianglePS] = ShaderByteCode(g_im3d_triangles_ps);
|
||||
|
||||
ui.Init(false, ShaderByteCode(g_ui_vs), ShaderByteCode(g_ui_ps), renderTargetFormat, descriptorTable, &rootSignatureDesc);
|
||||
world.Init();
|
||||
mipMapGen.Init(false, ShaderByteCode(g_mip_1_cs), ShaderByteCode(g_mip_2_cs), ShaderByteCode(g_mip_3_cs));
|
||||
const HTexture fontAtlas = imgui.Init(false, ShaderByteCode(g_imgui_vs), ShaderByteCode(g_imgui_ps), renderTargetFormat, descriptorTable, &rootSignatureDesc);
|
||||
const uint32_t fontAtlasSRV = RegisterTexture(fontAtlas);
|
||||
imgui.RegisterFontAtlas(fontAtlasSRV);
|
||||
im3d.Init(false, im3dShaders, renderTargetFormat);
|
||||
nuklear.Init(false, ShaderByteCode(g_nuklear_vs), ShaderByteCode(g_nuklear_ps), renderTargetFormat, descriptorTable, &rootSignatureDesc);
|
||||
post.Init();
|
||||
post.SetToneMapInput(renderTarget);
|
||||
|
@ -237,6 +249,7 @@ void GRP::BeginFrame()
|
|||
ui.BeginFrame();
|
||||
world.BeginFrame();
|
||||
nuklear.BeginFrame();
|
||||
im3d.BeginFrame();
|
||||
|
||||
CmdBeginBarrier();
|
||||
CmdTextureBarrier(renderTarget, ResourceStates::RenderTargetBit);
|
||||
|
@ -254,6 +267,7 @@ void GRP::BeginFrame()
|
|||
void GRP::EndFrame()
|
||||
{
|
||||
srp.DrawGUI();
|
||||
im3d.DrawGUI();
|
||||
imgui.Draw(renderTarget);
|
||||
post.Draw("Post-process", GetSwapChainTexture());
|
||||
world.EndFrame();
|
||||
|
@ -621,6 +635,7 @@ void GRP::ExecuteRenderCommands(const byte* data, bool readbackRequested)
|
|||
break;
|
||||
case RC_DRAW_SCENE_VIEW:
|
||||
world.DrawSceneView(*(const drawSceneViewCommand_t*)data);
|
||||
im3d.Draw(*(const drawSceneViewCommand_t*)data, renderTarget, world.depthTexture);
|
||||
break;
|
||||
case RC_BEGIN_FRAME:
|
||||
BeginFrame();
|
||||
|
|
|
@ -1697,7 +1697,7 @@ namespace RHI
|
|||
switch(descType)
|
||||
{
|
||||
case DescriptorType::Texture: return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
case DescriptorType::Buffer: return D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
||||
case DescriptorType::Buffer: return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
case DescriptorType::RWTexture: return D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
||||
case DescriptorType::RWBuffer: return D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
||||
case DescriptorType::Sampler: return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
|
@ -4629,6 +4629,15 @@ namespace RHI
|
|||
CopyDescriptor(table.genericHeap, update.firstIndex + i, rhi.descHeapGeneric, texture.srvIndex);
|
||||
}
|
||||
}
|
||||
else if(update.type == DescriptorType::Buffer && table.genericHeap)
|
||||
{
|
||||
for(uint32_t i = 0; i < update.resourceCount; ++i)
|
||||
{
|
||||
const Buffer& buffer = rhi.buffers.Get(update.buffers[i]);
|
||||
Q_assert(buffer.srvIndex != InvalidDescriptorIndex);
|
||||
CopyDescriptor(table.genericHeap, update.firstIndex + i, rhi.descHeapGeneric, buffer.srvIndex);
|
||||
}
|
||||
}
|
||||
else if(update.type == DescriptorType::RWBuffer && table.genericHeap)
|
||||
{
|
||||
for(uint32_t i = 0; i < update.resourceCount; ++i)
|
||||
|
|
|
@ -203,7 +203,7 @@ namespace RHI
|
|||
{
|
||||
enum Id
|
||||
{
|
||||
Buffer, // CBV, HBuffer
|
||||
Buffer, // SRV, HBuffer
|
||||
RWBuffer, // UAV, HBuffer
|
||||
Texture, // SRV, HTexture
|
||||
RWTexture, // UAV, HTexture
|
||||
|
@ -586,7 +586,7 @@ namespace RHI
|
|||
// note that for our texture UAVs,
|
||||
// we only allow 2 options:
|
||||
// 1) "bind all mips" (mip chain)
|
||||
// 2) "bind this single mip" (slide)
|
||||
// 2) "bind this single mip" (slice)
|
||||
|
||||
uint32_t firstIndex = 0;
|
||||
uint32_t resourceCount = 0;
|
||||
|
|
162
code/renderer/shaders/common/im3d.hlsli
Normal file
162
code/renderer/shaders/common/im3d.hlsli
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||
|
||||
This file is part of Challenge Quake 3 (CNQ3).
|
||||
|
||||
Challenge Quake 3 is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||
===========================================================================
|
||||
*/
|
||||
// Im3d integration
|
||||
|
||||
|
||||
#define kAntialiasing 2.0
|
||||
|
||||
struct VOut
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float4 color : COLOR0;
|
||||
#if defined(POINTS) || defined(LINES)
|
||||
float size : SIZE;
|
||||
#endif
|
||||
#if defined(POINTS)
|
||||
float2 texCoords : UV;
|
||||
#endif
|
||||
#if defined(LINES)
|
||||
float edgeDistance : EDGEDISTANCE;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#if VERTEX_SHADER
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float3 position;
|
||||
float size;
|
||||
uint color;
|
||||
};
|
||||
|
||||
struct Im3dVertexShaderInput
|
||||
{
|
||||
matrix viewMatrix;
|
||||
matrix projectionMatrix;
|
||||
float2 viewport;
|
||||
uint vertexOffset;
|
||||
StructuredBuffer<Vertex> vertexBuffer;
|
||||
uint vertexId;
|
||||
};
|
||||
|
||||
float4 UnpackIm3dColor(uint c)
|
||||
{
|
||||
uint4 u = uint4((c >> 24) & 0xFFu, (c >> 16) & 0xFFu, (c >> 8) & 0xFFu, c & 0xFFu);
|
||||
float4 r = float4(u) / 255.0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
float2 PositionFromVertexId(uint vertexId)
|
||||
{
|
||||
// 0 -> -1, -1
|
||||
// 1 -> 1, -1
|
||||
// 2 -> 1, 1
|
||||
// 3 -> -1, 1
|
||||
float2 result;
|
||||
result.x = (2 - vertexId) <= 1 ? 1.0 : -1.0;
|
||||
result.y = vertexId >= 2 ? 1.0 : -1.0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VOut VertexShader(Im3dVertexShaderInput input)
|
||||
{
|
||||
VOut output;
|
||||
|
||||
#if defined(POINTS)
|
||||
uint pointIndex = input.vertexOffset + (input.vertexId / 4);
|
||||
Vertex vertex = input.vertexBuffer[NonUniformResourceIndex(pointIndex)];
|
||||
float outSize = max(vertex.size, kAntialiasing);
|
||||
float2 scale = outSize.xx / input.viewport;
|
||||
float2 localPosition = PositionFromVertexId(input.vertexId % 4);
|
||||
float4 position = mul(input.projectionMatrix, mul(input.viewMatrix, float4(vertex.position, 1)));
|
||||
position.xy += localPosition * scale * position.w;
|
||||
|
||||
output.position = position;
|
||||
output.color = UnpackIm3dColor(vertex.color);
|
||||
output.size = outSize;
|
||||
output.texCoords = localPosition * 0.5 + 0.5;
|
||||
#endif
|
||||
#if defined(LINES)
|
||||
uint localVertexId = input.vertexId % 4;
|
||||
bool lineStart = localVertexId == 0 || localVertexId == 3;
|
||||
uint lineId = input.vertexId / 4;
|
||||
uint vid0 = input.vertexOffset + lineId * 2; // line start, x negative (0 or 3)
|
||||
uint vid1 = vid0 + 1; // line end, x positive (1 or 2)
|
||||
uint vid = lineStart ? vid0 : vid1; // data for this vertex
|
||||
Vertex vertex = input.vertexBuffer[NonUniformResourceIndex(vid)];
|
||||
Vertex vertex0 = input.vertexBuffer[NonUniformResourceIndex(vid0)];
|
||||
Vertex vertex1 = input.vertexBuffer[NonUniformResourceIndex(vid1)];
|
||||
float2 localPosition = PositionFromVertexId(localVertexId);
|
||||
float4 outColor = UnpackIm3dColor(vertex.color);
|
||||
float outSize = vertex.size;
|
||||
outColor.a *= smoothstep(0.0, 1.0, outSize / kAntialiasing);
|
||||
outSize = max(outSize, kAntialiasing);
|
||||
float edgeDistance = outSize * localPosition.y;
|
||||
float4 pos0 = mul(input.projectionMatrix, mul(input.viewMatrix, float4(vertex0.position, 1)));
|
||||
float4 pos1 = mul(input.projectionMatrix, mul(input.viewMatrix, float4(vertex1.position, 1)));
|
||||
float2 dir = (pos0.xy / pos0.w) - (pos1.xy / pos1.w);
|
||||
dir = normalize(float2(dir.x, dir.y * input.viewport.y / input.viewport.x)); // correct for aspect ratio
|
||||
float2 tng = float2(-dir.y, dir.x) * outSize / input.viewport;
|
||||
float4 position = lineStart ? pos0 : pos1;
|
||||
position.xy += tng * localPosition.y * position.w;
|
||||
|
||||
output.position = position;
|
||||
output.color = outColor;
|
||||
output.size = outSize;
|
||||
output.edgeDistance = edgeDistance;
|
||||
#endif
|
||||
#if defined(TRIANGLES)
|
||||
Vertex vertex = input.vertexBuffer[NonUniformResourceIndex(input.vertexOffset + input.vertexId)];
|
||||
|
||||
output.position = mul(input.projectionMatrix, mul(input.viewMatrix, float4(vertex.position, 1)));
|
||||
output.color = UnpackIm3dColor(vertex.color);
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if PIXEL_SHADER
|
||||
|
||||
float4 PixelShader(VOut input)
|
||||
{
|
||||
// we scale the color here to counter the post-process gamma/brightness
|
||||
float4 result = float4(input.color.rgb * 0.5, input.color.a);
|
||||
#if defined(POINTS)
|
||||
float d = length(input.texCoords - float2(0.5, 0.5));
|
||||
d = smoothstep(0.5, 0.5 - (kAntialiasing / input.size), d);
|
||||
result.a *= d;
|
||||
#endif
|
||||
#if defined(LINES)
|
||||
float d = abs(input.edgeDistance) / input.size;
|
||||
d = smoothstep(1.0, 1.0 - (kAntialiasing / input.size), d);
|
||||
result.a *= d;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
63
code/renderer/shaders/crp/im3d.hlsl
Normal file
63
code/renderer/shaders/crp/im3d.hlsl
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||
|
||||
This file is part of Challenge Quake 3 (CNQ3).
|
||||
|
||||
Challenge Quake 3 is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||
===========================================================================
|
||||
*/
|
||||
// Im3d integration
|
||||
|
||||
|
||||
#include "scene_view.h.hlsli"
|
||||
#include "../common/im3d.hlsli"
|
||||
|
||||
|
||||
#if VERTEX_SHADER
|
||||
|
||||
cbuffer RootConstants
|
||||
{
|
||||
float2 viewport;
|
||||
uint vertexBufferIndex;
|
||||
uint vertexOffset;
|
||||
};
|
||||
|
||||
VOut vs(uint vertexId : SV_VertexID)
|
||||
{
|
||||
SceneView scene = GetSceneView();
|
||||
StructuredBuffer<Vertex> vertexBuffer = ResourceDescriptorHeap[vertexBufferIndex];
|
||||
|
||||
Im3dVertexShaderInput input;
|
||||
input.viewMatrix = scene.viewMatrix;
|
||||
input.projectionMatrix = scene.projectionMatrix;
|
||||
input.viewport = viewport;
|
||||
input.vertexOffset = vertexOffset;
|
||||
input.vertexBuffer = vertexBuffer;
|
||||
input.vertexId = vertexId;
|
||||
|
||||
return VertexShader(input);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if PIXEL_SHADER
|
||||
|
||||
float4 ps(VOut input) : SV_Target
|
||||
{
|
||||
return PixelShader(input);
|
||||
}
|
||||
|
||||
#endif
|
62
code/renderer/shaders/grp/im3d.hlsl
Normal file
62
code/renderer/shaders/grp/im3d.hlsl
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||
|
||||
This file is part of Challenge Quake 3 (CNQ3).
|
||||
|
||||
Challenge Quake 3 is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||
===========================================================================
|
||||
*/
|
||||
// Im3d integration
|
||||
|
||||
|
||||
#include "../common/im3d.hlsli"
|
||||
|
||||
|
||||
#if VERTEX_SHADER
|
||||
|
||||
cbuffer RootConstants
|
||||
{
|
||||
matrix viewMatrix;
|
||||
matrix projectionMatrix;
|
||||
float2 viewport;
|
||||
uint vertexOffset;
|
||||
};
|
||||
|
||||
StructuredBuffer<Vertex> vertexBuffer : register(t0, space1);
|
||||
|
||||
VOut vs(uint vertexId : SV_VertexID)
|
||||
{
|
||||
Im3dVertexShaderInput input;
|
||||
input.viewMatrix = viewMatrix;
|
||||
input.projectionMatrix = projectionMatrix;
|
||||
input.viewport = viewport;
|
||||
input.vertexOffset = vertexOffset;
|
||||
input.vertexBuffer = vertexBuffer;
|
||||
input.vertexId = vertexId;
|
||||
|
||||
return VertexShader(input);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if PIXEL_SHADER
|
||||
|
||||
float4 ps(VOut input) : SV_Target
|
||||
{
|
||||
return PixelShader(input);
|
||||
}
|
||||
|
||||
#endif
|
368
code/renderer/srp_im3d.cpp
Normal file
368
code/renderer/srp_im3d.cpp
Normal file
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2024 Gian 'myT' Schellenbaum
|
||||
|
||||
This file is part of Challenge Quake 3 (CNQ3).
|
||||
|
||||
Challenge Quake 3 is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Challenge Quake 3 is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||
===========================================================================
|
||||
*/
|
||||
// Shared Rendering Pipeline - Im3d integration
|
||||
|
||||
|
||||
#include "srp_local.h"
|
||||
#include "../im3d/im3d.h"
|
||||
#include "../im3d/im3d_math.h"
|
||||
#include "../client/cl_imgui.h"
|
||||
|
||||
|
||||
#define MAX_VERTEX_COUNT 65536 // we use 16-bit indices
|
||||
#define MAX_INDEX_COUNT ((MAX_VERTEX_COUNT / 4) * 6)
|
||||
|
||||
|
||||
#pragma pack(push, 4)
|
||||
|
||||
struct Im3DVertexRC_CRP
|
||||
{
|
||||
vec2_t viewport;
|
||||
uint32_t vertexBufferIndex;
|
||||
uint32_t vertexOffset;
|
||||
};
|
||||
|
||||
struct Im3DVertexRC_GRP
|
||||
{
|
||||
matrix4x4_t viewMatrix;
|
||||
matrix4x4_t projectionMatrix;
|
||||
vec2_t viewport;
|
||||
uint32_t vertexOffset;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
static void SetupPipeline(
|
||||
Im3DVertexRC_CRP& crp, Im3DVertexRC_GRP& grp, bool ddhi, HPipeline pipeline,
|
||||
HRootSignature rootSignature, HDescriptorTable descriptorTable, uint32_t vertexOffset)
|
||||
{
|
||||
CmdBindPipeline(pipeline);
|
||||
if(ddhi)
|
||||
{
|
||||
crp.vertexOffset = vertexOffset;
|
||||
CmdSetGraphicsRootConstants(0, sizeof(crp), &crp);
|
||||
}
|
||||
else
|
||||
{
|
||||
grp.vertexOffset = vertexOffset;
|
||||
CmdSetRootConstants(rootSignature, ShaderStage::Vertex, &grp);
|
||||
}
|
||||
if(!ddhi)
|
||||
{
|
||||
CmdBindDescriptorTable(rootSignature, descriptorTable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Im3D::Init(bool ddhi_, const ShaderByteCode shaders[Im3D::Shader::Count], TextureFormat::Id rtFormat)
|
||||
{
|
||||
ddhi = ddhi_;
|
||||
|
||||
if(ddhi)
|
||||
{
|
||||
rootSignature = RHI_MAKE_NULL_HANDLE();
|
||||
}
|
||||
else
|
||||
{
|
||||
RootSignatureDesc desc("Im3d");
|
||||
desc.shortLifeTime = true;
|
||||
desc.AddRange(DescriptorType::Buffer, 0, 1);
|
||||
desc.constants[ShaderStage::Vertex].byteCount = sizeof(Im3DVertexRC_GRP);
|
||||
rootSignature = CreateRootSignature(desc);
|
||||
}
|
||||
|
||||
if(ddhi)
|
||||
{
|
||||
for(uint32_t i = 0; i < ARRAY_LEN(descriptorTables); i++)
|
||||
{
|
||||
descriptorTables[i] = RHI_MAKE_NULL_HANDLE();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint32_t i = 0; i < ARRAY_LEN(descriptorTables); i++)
|
||||
{
|
||||
DescriptorTableDesc desc("Im3d", rootSignature);
|
||||
desc.shortLifeTime = true;
|
||||
descriptorTables[i] = CreateDescriptorTable(desc);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
GraphicsPipelineDesc desc("Im3d point", rootSignature);
|
||||
desc.shortLifeTime = true;
|
||||
desc.vertexShader = shaders[Shader::PointVS];
|
||||
desc.pixelShader = shaders[Shader::PointPS];
|
||||
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||
desc.depthStencil.DisableDepth();
|
||||
desc.AddRenderTarget(GLS_BLEND_STD_ALPHA, rtFormat);
|
||||
pointPipeline = CreateGraphicsPipeline(desc);
|
||||
}
|
||||
|
||||
{
|
||||
GraphicsPipelineDesc desc("Im3d line", rootSignature);
|
||||
desc.shortLifeTime = true;
|
||||
desc.vertexShader = shaders[Shader::LineVS];
|
||||
desc.pixelShader = shaders[Shader::LinePS];
|
||||
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||
desc.depthStencil.DisableDepth();
|
||||
desc.AddRenderTarget(GLS_BLEND_STD_ALPHA, rtFormat);
|
||||
linePipeline = CreateGraphicsPipeline(desc);
|
||||
}
|
||||
|
||||
{
|
||||
GraphicsPipelineDesc desc("Im3d triangle", rootSignature);
|
||||
desc.shortLifeTime = true;
|
||||
desc.vertexShader = shaders[Shader::TriangleVS];
|
||||
desc.pixelShader = shaders[Shader::TrianglePS];
|
||||
desc.rasterizer.cullMode = CT_TWO_SIDED;
|
||||
desc.depthStencil.DisableDepth();
|
||||
desc.AddRenderTarget(GLS_BLEND_STD_ALPHA, rtFormat);
|
||||
trianglePipeline = CreateGraphicsPipeline(desc);
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t byteCount = sizeof(Im3d::VertexData) * MAX_VERTEX_COUNT;
|
||||
BufferDesc desc("", byteCount, ResourceStates::VertexShaderAccessBit);
|
||||
desc.shortLifeTime = true;
|
||||
desc.structureByteCount = sizeof(Im3d::VertexData);
|
||||
desc.memoryUsage = MemoryUsage::Upload;
|
||||
desc.name = "Im3d vertex #1";
|
||||
vertexBuffers[0] = CreateBuffer(desc);
|
||||
desc.name = "Im3d vertex #2";
|
||||
vertexBuffers[1] = CreateBuffer(desc);
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t byteCount = sizeof(uint16_t) * MAX_INDEX_COUNT;
|
||||
BufferDesc desc("Im3d index", byteCount, ResourceStates::IndexBufferBit);
|
||||
desc.shortLifeTime = true;
|
||||
indexBuffer = CreateBuffer(desc);
|
||||
|
||||
uint16_t* indices = (uint16_t*)BeginBufferUpload(indexBuffer);
|
||||
for(uint32_t i = 0, v = 0; i < MAX_INDEX_COUNT; i += 6, v += 4)
|
||||
{
|
||||
indices[i + 0] = v + 0;
|
||||
indices[i + 1] = v + 1;
|
||||
indices[i + 2] = v + 2;
|
||||
indices[i + 3] = v + 2;
|
||||
indices[i + 4] = v + 3;
|
||||
indices[i + 5] = v + 0;
|
||||
}
|
||||
EndBufferUpload(indexBuffer);
|
||||
}
|
||||
|
||||
if(!ddhi)
|
||||
{
|
||||
for(uint32_t i = 0; i < ARRAY_LEN(descriptorTables); i++)
|
||||
{
|
||||
DescriptorTableUpdate update;
|
||||
update.SetBuffers(1, &vertexBuffers[i]);
|
||||
UpdateDescriptorTable(descriptorTables[i], update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Im3D::BeginFrame()
|
||||
{
|
||||
const int currTime = Sys_Milliseconds();
|
||||
const int timeDelta = prevTime == INT_MIN ? 0 : currTime - prevTime;
|
||||
prevTime = currTime;
|
||||
|
||||
int x, y;
|
||||
Sys_GetCursorPosition(&x, &y);
|
||||
R_ComputeCursorPosition(&x, &y);
|
||||
|
||||
Im3d::AppData& ad = Im3d::GetAppData();
|
||||
ad.m_deltaTime = (float)timeDelta / 1000.0f;
|
||||
ad.m_viewportSize = Im3d::Vec2((float)glConfig.vidWidth, (float)glConfig.vidHeight);
|
||||
ad.m_viewOrigin = Im3d::Vec3(tr.rtRefdef.vieworg[0], tr.rtRefdef.vieworg[1], tr.rtRefdef.vieworg[2]);
|
||||
ad.m_viewDirection = Im3d::Vec3(tr.rtRefdef.viewaxis[0][0], tr.rtRefdef.viewaxis[0][1], tr.rtRefdef.viewaxis[0][2]);
|
||||
ad.m_worldUp = Im3d::Vec3(0.0f, 0.0f, 1.0f);
|
||||
ad.m_projScaleY = 2.0f * tanf(DEG2RAD(tr.rtRefdef.fov_y) * 0.5f);
|
||||
Im3d::Mat4 camWorld = LookAt(ad.m_viewOrigin, ad.m_viewOrigin + ad.m_viewDirection, ad.m_worldUp);
|
||||
Im3d::Vec2 cursorNDC;
|
||||
cursorNDC.x = ((float)x / (float)glConfig.vidWidth ) * -2.0f + 1.0f;
|
||||
cursorNDC.y = ((float)y / (float)glConfig.vidHeight) * -2.0f + 1.0f;
|
||||
Im3d::Vec3 rayOrigin, rayDirection;
|
||||
rayOrigin = ad.m_viewOrigin;
|
||||
rayDirection.x = tanf(0.5f * DEG2RAD(tr.rtRefdef.fov_x)) * cursorNDC.x;
|
||||
rayDirection.y = tanf(0.5f * DEG2RAD(tr.rtRefdef.fov_y)) * cursorNDC.y;
|
||||
rayDirection.z = 1.0f;
|
||||
rayDirection = camWorld * Im3d::Vec4(Im3d::Normalize(rayDirection), 0.0f);
|
||||
ad.m_cursorRayOrigin = rayOrigin;
|
||||
ad.m_cursorRayDirection = rayDirection;
|
||||
if(r_debugInput->integer == 0 || ImGui::GetIO().WantCaptureMouse)
|
||||
{
|
||||
ad.m_cursorRayOrigin = Im3d::Vec3(0.0f, 0.0f, 0.0f);
|
||||
ad.m_cursorRayDirection = Im3d::Vec3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
Im3d::NewFrame();
|
||||
}
|
||||
|
||||
void Im3D::Draw(const drawSceneViewCommand_t& cmd, HTexture colorTarget, HTexture depthTarget)
|
||||
{
|
||||
#if 0 // cpm3 test/demo code
|
||||
{
|
||||
static Im3d::Vec3 translation(700, 50, -50);
|
||||
static Im3d::Mat3 rotation(1.0f);
|
||||
static Im3d::Vec3 scale(1.0f);
|
||||
Im3d::PushMatrix(Im3d::Mat4(translation, rotation, scale));
|
||||
if(ShouldDrawGizmos())
|
||||
{
|
||||
Im3d::Gizmo("Test", translation, rotation, scale);
|
||||
}
|
||||
Im3d::DrawConeFilled(Im3d::Vec3(0, 0, 0), Im3d::Vec3(0, 0, 1), 32.0f, 8.0f, 16);
|
||||
Im3d::PopMatrix();
|
||||
|
||||
Im3d::DrawPoint(Im3d::Vec3(700, 0, 0), 16.0f, Im3d::Color(1, 0, 0, 1));
|
||||
Im3d::DrawPoint(Im3d::Vec3(725, 0, 0), 16.0f, Im3d::Color(0, 1, 0, 1));
|
||||
Im3d::DrawPoint(Im3d::Vec3(750, 0, 0), 16.0f, Im3d::Color(0, 0, 1, 1));
|
||||
Im3d::DrawLine(Im3d::Vec3(700, 0, -100), Im3d::Vec3(750, 0, -100), 4.0f, Im3d::Color(1, 0, 0, 1));
|
||||
Im3d::DrawLine(Im3d::Vec3(700, 0, -110), Im3d::Vec3(750, 0, -110), 4.0f, Im3d::Color(0, 1, 0, 1));
|
||||
Im3d::DrawLine(Im3d::Vec3(700, 0, -120), Im3d::Vec3(750, 0, -120), 4.0f, Im3d::Color(0, 0, 1, 1));
|
||||
Im3d::SetColor(0, 1, 0, 1);
|
||||
Im3d::SetSize(4.0f);
|
||||
Im3d::DrawArrow(Im3d::Vec3(700, 0, -150), Im3d::Vec3(750, 0, -150), 10.0f, 10.0f);
|
||||
Im3d::DrawConeFilled(Im3d::Vec3(725, 0, -200), Im3d::Vec3(0, 0, 1), 32.0f, 8.0f, 16);
|
||||
}
|
||||
#endif
|
||||
|
||||
Im3d::EndFrame();
|
||||
|
||||
if(!ShouldDrawShapes())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Im3d::U32 drawListCount = Im3d::GetDrawListCount();
|
||||
if(drawListCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SCOPED_DEBUG_LABEL("Im3d", 1.0f, 1.0f, 1.0f);
|
||||
|
||||
CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
||||
|
||||
CmdBeginBarrier();
|
||||
CmdTextureBarrier(colorTarget, ResourceStates::RenderTargetBit);
|
||||
CmdEndBarrier();
|
||||
|
||||
CmdBindRenderTargets(1, &colorTarget, NULL);
|
||||
CmdBindIndexBuffer(indexBuffer, IndexType::UInt16, 0);
|
||||
|
||||
const uint32_t frameIndex = GetFrameIndex();
|
||||
const HBuffer vertexBuffer = vertexBuffers[frameIndex];
|
||||
|
||||
Im3DVertexRC_CRP vertexRC_CRP;
|
||||
Im3DVertexRC_GRP vertexRC_GRP;
|
||||
if(ddhi)
|
||||
{
|
||||
vertexRC_CRP = {};
|
||||
vertexRC_CRP.vertexBufferIndex = GetBufferIndexSRV(vertexBuffer);
|
||||
vertexRC_CRP.viewport[0] = (float)glConfig.vidWidth;
|
||||
vertexRC_CRP.viewport[1] = (float)glConfig.vidHeight;
|
||||
CmdSetGraphicsRootConstants(0, sizeof(vertexRC_CRP), &vertexRC_CRP);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexRC_GRP = {};
|
||||
vertexRC_GRP.viewport[0] = (float)glConfig.vidWidth;
|
||||
vertexRC_GRP.viewport[1] = (float)glConfig.vidHeight;
|
||||
memcpy(vertexRC_GRP.viewMatrix, cmd.viewParms.world.modelMatrix, sizeof(vertexRC_GRP.viewMatrix));
|
||||
memcpy(vertexRC_GRP.projectionMatrix, cmd.viewParms.projectionMatrix, sizeof(vertexRC_GRP.projectionMatrix));
|
||||
CmdSetRootConstants(rootSignature, ShaderStage::Vertex, &vertexRC_GRP);
|
||||
}
|
||||
|
||||
Im3d::VertexData* vertices = (Im3d::VertexData*)MapBuffer(vertexBuffer);
|
||||
|
||||
uint32_t vertexOffset = 0;
|
||||
for(Im3d::U32 i = 0; i < drawListCount; i++)
|
||||
{
|
||||
const Im3d::DrawList& drawList = Im3d::GetDrawLists()[i];
|
||||
switch(drawList.m_primType)
|
||||
{
|
||||
case Im3d::DrawPrimitive_Triangles:
|
||||
{
|
||||
const uint32_t pointCount = (uint32_t)drawList.m_vertexCount;
|
||||
const uint32_t indexCount = pointCount;
|
||||
Q_assert(pointCount % 3 == 0);
|
||||
memcpy(vertices, drawList.m_vertexData, (size_t)pointCount * sizeof(Im3d::VertexData));
|
||||
SetupPipeline(vertexRC_CRP, vertexRC_GRP, ddhi, trianglePipeline, rootSignature, descriptorTables[frameIndex], vertexOffset);
|
||||
CmdDraw(indexCount, 0);
|
||||
vertexOffset += pointCount;
|
||||
vertices += pointCount;
|
||||
break;
|
||||
}
|
||||
case Im3d::DrawPrimitive_Lines:
|
||||
{
|
||||
const uint32_t pointCount = (uint32_t)drawList.m_vertexCount;
|
||||
const uint32_t indexCount = pointCount * 3;
|
||||
Q_assert(pointCount % 2 == 0);
|
||||
memcpy(vertices, drawList.m_vertexData, (size_t)pointCount * sizeof(Im3d::VertexData));
|
||||
SetupPipeline(vertexRC_CRP, vertexRC_GRP, ddhi, linePipeline, rootSignature, descriptorTables[frameIndex], vertexOffset);
|
||||
CmdDrawIndexed(indexCount, 0, 0);
|
||||
vertexOffset += pointCount;
|
||||
vertices += pointCount;
|
||||
break;
|
||||
}
|
||||
case Im3d::DrawPrimitive_Points:
|
||||
{
|
||||
const uint32_t pointCount = (uint32_t)drawList.m_vertexCount;
|
||||
const uint32_t indexCount = pointCount * 6;
|
||||
memcpy(vertices, drawList.m_vertexData, (size_t)pointCount * sizeof(Im3d::VertexData));
|
||||
SetupPipeline(vertexRC_CRP, vertexRC_GRP, ddhi, pointPipeline, rootSignature, descriptorTables[frameIndex], vertexOffset);
|
||||
CmdDrawIndexed(indexCount, 0, 0);
|
||||
vertexOffset += pointCount;
|
||||
vertices += pointCount;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Q_assert(!"Invalid primitive type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UnmapBuffer(vertexBuffer);
|
||||
}
|
||||
|
||||
void Im3D::DrawGUI()
|
||||
{
|
||||
if(ImGui::IsKeyDown(ImGuiMod_Shift) && ImGui::IsKeyPressed(ImGuiKey_G, false))
|
||||
{
|
||||
drawGizmos = !drawGizmos;
|
||||
}
|
||||
GUI_AddMainMenuItem(GUI_MainMenu::Im3D, "Enable", "", &drawIm3d);
|
||||
GUI_AddMainMenuItem(GUI_MainMenu::Im3D, "Draw Gizmos", "Shift+G", &drawGizmos);
|
||||
}
|
||||
|
||||
bool Im3D::ShouldDrawShapes()
|
||||
{
|
||||
return drawIm3d;
|
||||
}
|
||||
|
||||
bool Im3D::ShouldDrawGizmos()
|
||||
{
|
||||
return drawIm3d && drawGizmos && r_debugInput->integer != 0;
|
||||
}
|
|
@ -317,6 +317,43 @@ private:
|
|||
bool ddhi = false;
|
||||
};
|
||||
|
||||
struct Im3D
|
||||
{
|
||||
struct Shader
|
||||
{
|
||||
enum Id
|
||||
{
|
||||
PointVS,
|
||||
PointPS,
|
||||
LineVS,
|
||||
LinePS,
|
||||
TriangleVS,
|
||||
TrianglePS,
|
||||
Count
|
||||
};
|
||||
};
|
||||
|
||||
void Init(bool ddhi_, const ShaderByteCode shaders[Shader::Count], TextureFormat::Id rtFormat);
|
||||
void BeginFrame();
|
||||
void Draw(const drawSceneViewCommand_t& cmd, HTexture colorTarget, HTexture depthTarget);
|
||||
void DrawGUI();
|
||||
bool ShouldDrawShapes();
|
||||
bool ShouldDrawGizmos();
|
||||
|
||||
private:
|
||||
HRootSignature rootSignature;
|
||||
HDescriptorTable descriptorTables[RHI::FrameCount];
|
||||
HPipeline pointPipeline;
|
||||
HPipeline linePipeline;
|
||||
HPipeline trianglePipeline;
|
||||
HBuffer vertexBuffers[RHI::FrameCount];
|
||||
HBuffer indexBuffer;
|
||||
int prevTime = INT_MIN;
|
||||
bool ddhi;
|
||||
bool drawGizmos = true;
|
||||
bool drawIm3d = true;
|
||||
};
|
||||
|
||||
struct Nuklear
|
||||
{
|
||||
void Init(bool ddhi, const ShaderByteCode& vs, const ShaderByteCode& ps, TextureFormat::Id rtFormat, HDescriptorTable descTable, RootSignatureDesc* rootSigDesc);
|
||||
|
|
|
@ -1926,7 +1926,10 @@ void RE_DrawMainMenuBarInfo()
|
|||
frameCount = 0;
|
||||
}
|
||||
|
||||
const char* const info = va("%s | %s | %3d FPS", rhiInfo.adapter, Com_FormatBytes(rhiInfo.allocatedByteCount), displayedFPS);
|
||||
const char* const pipeline = r_pipeline->integer == 1 ? "CRP" : "GRP";
|
||||
const char* const info = va(
|
||||
"%s | %s | %s | %3d FPS",
|
||||
pipeline, rhiInfo.adapter, Com_FormatBytes(rhiInfo.allocatedByteCount), displayedFPS);
|
||||
const float offset = ImGui::GetWindowWidth() - ImGui::CalcTextSize("___").x - ImGui::CalcTextSize(info).x;
|
||||
ImGui::SameLine(offset);
|
||||
ImGui::Text(info);
|
||||
|
|
|
@ -866,7 +866,7 @@ static qbool RE_IsDepthClampEnabled()
|
|||
}
|
||||
|
||||
|
||||
static void RE_ComputeCursorPosition( int* x, int* y )
|
||||
void R_ComputeCursorPosition( int* x, int* y )
|
||||
{
|
||||
if ( r_fullscreen->integer != 1 || r_mode->integer != VIDEOMODE_UPSCALE ) {
|
||||
return;
|
||||
|
@ -956,7 +956,7 @@ const refexport_t* GetRefAPI( const refimport_t* rimp )
|
|||
|
||||
re.DepthClamp = RE_IsDepthClampEnabled;
|
||||
|
||||
re.ComputeCursorPosition = RE_ComputeCursorPosition;
|
||||
re.ComputeCursorPosition = R_ComputeCursorPosition;
|
||||
|
||||
return &re;
|
||||
}
|
||||
|
|
|
@ -1681,6 +1681,8 @@ void R_MakeOrthoProjectionMatrix( matrix4x4_t m, float w, float h );
|
|||
void R_LinearDepthConstantsFromClipPlanes( float zNear, float zFar, vec3_t constants );
|
||||
void RB_LinearDepthConstants( vec3_t constants );
|
||||
|
||||
void R_ComputeCursorPosition( int* x, int* y );
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -390,6 +390,9 @@ void ProcessGRP()
|
|||
CompileCompute("mip_1.h", "mip_1.hlsl", "mip_1");
|
||||
CompileCompute("mip_2.h", "mip_2.hlsl", "mip_2");
|
||||
CompileCompute("mip_3.h", "mip_3.hlsl", "mip_3");
|
||||
CompileGraphics("im3d_points.h", "im3d.hlsl", "im3d_points", 1, 1, "-D POINTS=1", "-D POINTS=1");
|
||||
CompileGraphics("im3d_lines.h", "im3d.hlsl", "im3d_lines", 1, 1, "-D LINES=1", "-D LINES=1");
|
||||
CompileGraphics("im3d_triangles.h", "im3d.hlsl", "im3d_triangles", 1, 1, "-D TRIANGLES=1", "-D TRIANGLES=1");
|
||||
|
||||
CompileSMAAShaders();
|
||||
system(va("type %s\\smaa*.h > %s\\complete_smaa.h", outputPath, outputPath));
|
||||
|
@ -506,6 +509,9 @@ void ProcessCRP()
|
|||
CompileCompute("particles_setup.h", "particles_setup.hlsl", "particles_setup");
|
||||
CompileCompute("particles_emit.h", "particles_emit.hlsl", "particles_emit");
|
||||
CompileCompute("particles_simulate.h", "particles_simulate.hlsl", "particles_simulate");
|
||||
CompileGraphics("im3d_points.h", "im3d.hlsl", "im3d_points", 1, 1, "-D POINTS=1", "-D POINTS=1");
|
||||
CompileGraphics("im3d_lines.h", "im3d.hlsl", "im3d_lines", 1, 1, "-D LINES=1", "-D LINES=1");
|
||||
CompileGraphics("im3d_triangles.h", "im3d.hlsl", "im3d_triangles", 1, 1, "-D TRIANGLES=1", "-D TRIANGLES=1");
|
||||
}
|
||||
|
||||
int main(int /*argc*/, const char** argv)
|
||||
|
|
|
@ -416,6 +416,7 @@ local function ApplyExeProjectSettings(exeName, server)
|
|||
AddSourcesFromArray(".", server_sources)
|
||||
else
|
||||
AddSourcesFromArray(".", client_sources)
|
||||
AddSourcesAndHeaders("im3d")
|
||||
AddSourcesAndHeaders("imgui")
|
||||
AddSourcesAndHeaders("implot")
|
||||
AddHeaders("renderer")
|
||||
|
|
|
@ -168,6 +168,9 @@ copy "..\..\.bin\release\cnq3.pdb" "$(QUAKE3DIR)"</Command>
|
|||
<ClInclude Include="..\..\code\client\snd_codec.h" />
|
||||
<ClInclude Include="..\..\code\client\snd_local.h" />
|
||||
<ClInclude Include="..\..\code\client\snd_public.h" />
|
||||
<ClInclude Include="..\..\code\im3d\im3d.h" />
|
||||
<ClInclude Include="..\..\code\im3d\im3d_config.h" />
|
||||
<ClInclude Include="..\..\code\im3d\im3d_math.h" />
|
||||
<ClInclude Include="..\..\code\imgui\font_proggy_clean.h" />
|
||||
<ClInclude Include="..\..\code\imgui\font_sweet16_mono.h" />
|
||||
<ClInclude Include="..\..\code\imgui\imconfig.h" />
|
||||
|
@ -239,6 +242,7 @@ copy "..\..\.bin\release\cnq3.pdb" "$(QUAKE3DIR)"</Command>
|
|||
<ClCompile Include="..\..\code\client\snd_main.cpp" />
|
||||
<ClCompile Include="..\..\code\client\snd_mem.cpp" />
|
||||
<ClCompile Include="..\..\code\client\snd_mix.cpp" />
|
||||
<ClCompile Include="..\..\code\im3d\im3d.cpp" />
|
||||
<ClCompile Include="..\..\code\imgui\imgui.cpp" />
|
||||
<ClCompile Include="..\..\code\imgui\imgui_demo.cpp" />
|
||||
<ClCompile Include="..\..\code\imgui\imgui_draw.cpp" />
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
<Filter Include="client">
|
||||
<UniqueIdentifier>{8461ABF6-7003-D6CC-59BE-E92045FF5C1D}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="im3d">
|
||||
<UniqueIdentifier>{F279987C-DEB0-990D-879D-7F1073B3150F}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="imgui">
|
||||
<UniqueIdentifier>{0098A80F-6CAC-D0C0-352E-7420A101CDF1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
@ -150,6 +153,15 @@
|
|||
<ClInclude Include="..\..\code\client\snd_public.h">
|
||||
<Filter>client</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\code\im3d\im3d.h">
|
||||
<Filter>im3d</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\code\im3d\im3d_config.h">
|
||||
<Filter>im3d</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\code\im3d\im3d_math.h">
|
||||
<Filter>im3d</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\code\imgui\font_proggy_clean.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
|
@ -359,6 +371,9 @@
|
|||
<ClCompile Include="..\..\code\client\snd_mix.cpp">
|
||||
<Filter>client</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\code\im3d\im3d.cpp">
|
||||
<Filter>im3d</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\code\imgui\imgui.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
<ClCompile Include="..\..\code\renderer\grp_smaa.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\grp_world.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\rhi_d3d12.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_im3d.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_imgui.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_main.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_mip_gen.cpp" />
|
||||
|
@ -243,6 +244,9 @@
|
|||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_position.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\crp\im3d.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\crp\imgui.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
|
@ -402,6 +406,9 @@
|
|||
<FxCompile Include="..\..\code\renderer\shaders\grp\fog_outside.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\grp\im3d.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\grp\imgui.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
|
@ -441,6 +448,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\code\renderer\shaders\common\blend.hlsli" />
|
||||
<None Include="..\..\code\renderer\shaders\common\im3d.hlsli" />
|
||||
<None Include="..\..\code\renderer\shaders\common\mip_gen.hlsli" />
|
||||
<None Include="..\..\code\renderer\shaders\common\state_bits.h.hlsli" />
|
||||
<None Include="..\..\code\renderer\shaders\crp\alpha_test.h.hlsli" />
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
<ClCompile Include="..\..\code\renderer\grp_smaa.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\grp_world.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\rhi_d3d12.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_im3d.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_imgui.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_main.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_mip_gen.cpp" />
|
||||
|
@ -149,6 +150,9 @@
|
|||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_position.hlsl">
|
||||
<Filter>shaders\crp</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\crp\im3d.hlsl">
|
||||
<Filter>shaders\crp</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\crp\imgui.hlsl">
|
||||
<Filter>shaders\crp</Filter>
|
||||
</FxCompile>
|
||||
|
@ -308,6 +312,9 @@
|
|||
<FxCompile Include="..\..\code\renderer\shaders\grp\fog_outside.hlsl">
|
||||
<Filter>shaders\grp</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\grp\im3d.hlsl">
|
||||
<Filter>shaders\grp</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\grp\imgui.hlsl">
|
||||
<Filter>shaders\grp</Filter>
|
||||
</FxCompile>
|
||||
|
@ -349,6 +356,9 @@
|
|||
<None Include="..\..\code\renderer\shaders\common\blend.hlsli">
|
||||
<Filter>shaders\common</Filter>
|
||||
</None>
|
||||
<None Include="..\..\code\renderer\shaders\common\im3d.hlsli">
|
||||
<Filter>shaders\common</Filter>
|
||||
</None>
|
||||
<None Include="..\..\code\renderer\shaders\common\mip_gen.hlsli">
|
||||
<Filter>shaders\common</Filter>
|
||||
</None>
|
||||
|
|
|
@ -170,6 +170,9 @@ copy "..\..\.bin\release\cnq3.pdb" "$(QUAKE3DIR)"</Command>
|
|||
<ClInclude Include="..\..\code\client\snd_codec.h" />
|
||||
<ClInclude Include="..\..\code\client\snd_local.h" />
|
||||
<ClInclude Include="..\..\code\client\snd_public.h" />
|
||||
<ClInclude Include="..\..\code\im3d\im3d.h" />
|
||||
<ClInclude Include="..\..\code\im3d\im3d_config.h" />
|
||||
<ClInclude Include="..\..\code\im3d\im3d_math.h" />
|
||||
<ClInclude Include="..\..\code\imgui\font_proggy_clean.h" />
|
||||
<ClInclude Include="..\..\code\imgui\font_sweet16_mono.h" />
|
||||
<ClInclude Include="..\..\code\imgui\imconfig.h" />
|
||||
|
@ -241,6 +244,7 @@ copy "..\..\.bin\release\cnq3.pdb" "$(QUAKE3DIR)"</Command>
|
|||
<ClCompile Include="..\..\code\client\snd_main.cpp" />
|
||||
<ClCompile Include="..\..\code\client\snd_mem.cpp" />
|
||||
<ClCompile Include="..\..\code\client\snd_mix.cpp" />
|
||||
<ClCompile Include="..\..\code\im3d\im3d.cpp" />
|
||||
<ClCompile Include="..\..\code\imgui\imgui.cpp" />
|
||||
<ClCompile Include="..\..\code\imgui\imgui_demo.cpp" />
|
||||
<ClCompile Include="..\..\code\imgui\imgui_draw.cpp" />
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
<Filter Include="client">
|
||||
<UniqueIdentifier>{8461ABF6-7003-D6CC-59BE-E92045FF5C1D}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="im3d">
|
||||
<UniqueIdentifier>{F279987C-DEB0-990D-879D-7F1073B3150F}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="imgui">
|
||||
<UniqueIdentifier>{0098A80F-6CAC-D0C0-352E-7420A101CDF1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
@ -150,6 +153,15 @@
|
|||
<ClInclude Include="..\..\code\client\snd_public.h">
|
||||
<Filter>client</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\code\im3d\im3d.h">
|
||||
<Filter>im3d</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\code\im3d\im3d_config.h">
|
||||
<Filter>im3d</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\code\im3d\im3d_math.h">
|
||||
<Filter>im3d</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\code\imgui\font_proggy_clean.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
|
@ -359,6 +371,9 @@
|
|||
<ClCompile Include="..\..\code\client\snd_mix.cpp">
|
||||
<Filter>client</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\code\im3d\im3d.cpp">
|
||||
<Filter>im3d</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\code\imgui\imgui.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
<ClCompile Include="..\..\code\renderer\grp_smaa.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\grp_world.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\rhi_d3d12.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_im3d.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_imgui.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_main.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_mip_gen.cpp" />
|
||||
|
@ -245,6 +246,9 @@
|
|||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_position.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\crp\im3d.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\crp\imgui.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
|
@ -404,6 +408,9 @@
|
|||
<FxCompile Include="..\..\code\renderer\shaders\grp\fog_outside.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\grp\im3d.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\grp\imgui.hlsl">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</FxCompile>
|
||||
|
@ -443,6 +450,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\code\renderer\shaders\common\blend.hlsli" />
|
||||
<None Include="..\..\code\renderer\shaders\common\im3d.hlsli" />
|
||||
<None Include="..\..\code\renderer\shaders\common\mip_gen.hlsli" />
|
||||
<None Include="..\..\code\renderer\shaders\common\state_bits.h.hlsli" />
|
||||
<None Include="..\..\code\renderer\shaders\crp\alpha_test.h.hlsli" />
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
<ClCompile Include="..\..\code\renderer\grp_smaa.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\grp_world.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\rhi_d3d12.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_im3d.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_imgui.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_main.cpp" />
|
||||
<ClCompile Include="..\..\code\renderer\srp_mip_gen.cpp" />
|
||||
|
@ -149,6 +150,9 @@
|
|||
<FxCompile Include="..\..\code\renderer\shaders\crp\gbufferviz_position.hlsl">
|
||||
<Filter>shaders\crp</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\crp\im3d.hlsl">
|
||||
<Filter>shaders\crp</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\crp\imgui.hlsl">
|
||||
<Filter>shaders\crp</Filter>
|
||||
</FxCompile>
|
||||
|
@ -308,6 +312,9 @@
|
|||
<FxCompile Include="..\..\code\renderer\shaders\grp\fog_outside.hlsl">
|
||||
<Filter>shaders\grp</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\grp\im3d.hlsl">
|
||||
<Filter>shaders\grp</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="..\..\code\renderer\shaders\grp\imgui.hlsl">
|
||||
<Filter>shaders\grp</Filter>
|
||||
</FxCompile>
|
||||
|
@ -349,6 +356,9 @@
|
|||
<None Include="..\..\code\renderer\shaders\common\blend.hlsli">
|
||||
<Filter>shaders\common</Filter>
|
||||
</None>
|
||||
<None Include="..\..\code\renderer\shaders\common\im3d.hlsli">
|
||||
<Filter>shaders\common</Filter>
|
||||
</None>
|
||||
<None Include="..\..\code\renderer\shaders\common\mip_gen.hlsli">
|
||||
<Filter>shaders\common</Filter>
|
||||
</None>
|
||||
|
|
Loading…
Reference in a new issue