File GOPrimitive.h¶
File List > AIAC > GOSys > GOPrimitive.h
Go to the documentation of this file
// #####################################################################
// >>>>>>>>>>>>>>>>>>>>> BEGINNING OF LEGAL NOTICE >>>>>>>>>>>>>>>>>>>>>
//######################################################################
//
// This source file, along with its associated content, was authored by
// Andrea Settimi, Hong-Bin Yang, Naravich Chutisilp, and numerous other
// contributors. The code was originally developed at the Laboratory for
// Timber Construction (IBOIS, director: Prof. Yves Weinand) at the School of
// Architecture, Civil and Environmental Engineering (ENAC) at the Swiss
// Federal Institute of Technology in Lausanne (EPFL) for the Doctoral
// Research "Augmented Carpentry" (PhD researcher: Andrea Settimi,
// co-director: Dr. Julien Gamerro, director: Prof. Yves Weinand).
//
// Although the entire repository is distributed under the GPL license,
// these particular source files may also be used under the terms of the
// MIT license. By accessing or using this file, you agree to the following:
//
// 1. You may reproduce, modify, and distribute this file in accordance
// with the terms of the MIT license.
// 2. You must retain this legal notice in all copies or substantial
// portions of this file.
// 3. This file is provided "AS IS," without any express or implied
// warranties, including but not limited to the implied warranties of
// merchantability and fitness for a particular purpose.
//
// If you cannot or will not comply with the above conditions, you are
// not permitted to use this file. By proceeding, you acknowledge and
// accept all terms and conditions herein.
//
//######################################################################
// <<<<<<<<<<<<<<<<<<<<<<< END OF LEGAL NOTICE <<<<<<<<<<<<<<<<<<<<<<<<
// #####################################################################
//
#pragma once
#include <utility>
#include <iostream>
#include "AIAC/Render/GLObject.h"
#include "AIAC/Base.h"
#include "glm/glm.hpp"
#include <glm/glm.hpp>
#include <glm/gtx/norm.hpp> // For glm::length2
#include <glm/gtc/constants.hpp> // For glm::pi
namespace AIAC
{
struct GOColor
{
static constexpr glm::vec4 RED = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
static constexpr glm::vec4 RED_TRANSP07 = glm::vec4(1.0f, 0.0f, 0.0f, 0.7f);
static constexpr glm::vec4 GREEN = glm::vec4(0.0f, 1.0f, 0.0f, 1.0f);
static constexpr glm::vec4 GREEN_TRANSP07 = glm::vec4(0.0f, 1.0f, 0.0f, 0.7f);
static constexpr glm::vec4 GREEN_DARKER_TRANSP07 = glm::vec4(0.0f, 0.7f, 0.0f, 0.7f);
static constexpr glm::vec4 GREEN_PUNK_TRANSP07 = glm::vec4(0.0f, 0.7f, 0.0f, 0.7f);
static constexpr glm::vec4 BLUE = glm::vec4(0.0f, 0.0f, 1.0f, 1.0f);
static constexpr glm::vec4 YELLOW = glm::vec4(1.0f, 1.0f, 0.0f, 1.0f);
static constexpr glm::vec4 YELLOW_TRANSP07 = glm::vec4(1.0f, 1.0f, 0.0f, 0.7f);
static constexpr glm::vec4 MAGENTA = glm::vec4(1.0f, 0.0f, 1.0f, 1.0f);
static constexpr glm::vec4 MAGENTA_TRANSP07 = glm::vec4(1.0f, 0.0f, 1.0f, 0.7f);
static constexpr glm::vec4 CYAN = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f);
static constexpr glm::vec4 WHITE = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
static constexpr glm::vec4 BLACK = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
static constexpr glm::vec4 GRAY = glm::vec4(0.5f, 0.5f, 0.5f, 1.0f);
static constexpr glm::vec4 ORANGE = glm::vec4(1.0f, 0.5f, 0.0f, 1.0f);
static constexpr glm::vec4 ORANGE_TRANSP = glm::vec4(1.0f, 0.5f, 0.0f, 0.5f);
static constexpr glm::vec4 PURPLE = glm::vec4(0.5f, 0.0f, 0.5f, 1.0f);
static constexpr glm::vec4 PURPLE_TRANSP = glm::vec4(0.5f, 0.0f, 0.5f, 0.5f);
static constexpr glm::vec4 PURPLE_TRANSP07 = glm::vec4(0.5f, 0.0f, 0.5f, 0.7f);
static constexpr glm::vec4 PINK = glm::vec4(1.0f, 0.0f, 0.5f, 1.0f);
static constexpr glm::vec4 PINK_TRANSP = glm::vec4(1.0f, 0.0f, 0.5f, 0.5f);
static constexpr glm::vec4 PINK_TRANSP07 = glm::vec4(1.0f, 0.0f, 0.5f, 0.7f);
static constexpr glm::vec4 BROWN = glm::vec4(0.5f, 0.25f, 0.0f, 1.0f);
};
struct GOWeight
{
static constexpr float Default = 1.01f;
static constexpr float Light = 1.4f;
static constexpr float Medium = 1.8f;
static constexpr float Bold = 2.5f;
static constexpr float Thick = 5.0f;
static constexpr float MediumThick = 7.0f;
static constexpr float ExtraThick = 10.0f;
static constexpr float BoldThick = 15.0f;
static constexpr float MaxThick = 20.0f;
};
struct GOTextSize
{
static constexpr double Default = 1.0;
static constexpr double ExtraSmall = 0.35;
static constexpr double BitSmall = 0.4;
static constexpr double Small = 0.5;
static constexpr double Average = 0.75;
static constexpr double Medium = 5.0;
static constexpr double Big = 10.0;
};
enum GOTypeFlags
{
_GOPrimitive = 0,
_GOPoint,
_GOLine,
_GOCircle,
_GOCylinder,
_GOPolyline,
_GOTriangle,
_GOMesh,
_GOText,
};
class GOPrimitive
{
public:
explicit GOPrimitive(bool isVisible = true,
glm::vec4 color = glm::vec4(0, 0, 0, 1.0));
virtual ~GOPrimitive() = default;
static void Remove(const uint32_t& id);
static void Remove(const std::shared_ptr<GOPrimitive>& ptrGO);
uint32_t GenerateId();
inline bool IsVisible() const { return m_IsVisible; }
inline glm::vec4 GetColor() const { return m_Color; }
inline bool GetState() { return m_State; }
inline GOTypeFlags GetType() { return m_Type; }
inline uint32_t GetId() { return m_Id; }
inline void SetName(std::string name) { m_Name = std::move(name); }
inline void SetVisibility(bool isVisible) { m_IsVisible = isVisible; }
inline bool GetVisibility() { return m_IsVisible; }
inline void SetColor(glm::vec4 color) { m_Color = color; InitGLObject();}
inline void SetState(bool state) { m_State = state; }
inline std::string GetName() const { return m_Name; }
inline float GetWeight() const { return m_Weight; }
inline int SetWeight(float weight) { m_Weight = weight; InitGLObject(); return m_Id;}
virtual void Transform(const glm::mat4x4& transformMat) {};
virtual void Translate(const glm::vec3& translation) {};
virtual void SetValueFrom(const std::shared_ptr<GOPrimitive>& ptrGO) { AIAC_ERROR("Not Implemented"); };
inline void Draw() { for(auto glObject : m_GLObjects) glObject->Draw(); }
void ClearGLObject();
virtual void InitGLObject() {}
protected:
std::string m_Name;
uint32_t m_Id;
bool m_IsVisible;
glm::vec4 m_Color;
bool m_State;
GOTypeFlags m_Type;
float m_Weight = GOWeight::Default;
std::vector<std::shared_ptr<GLObject> > m_GLObjects;
};
class GOPoint : public GOPrimitive
{
public:
GOPoint() = default;
GOPoint(float x, float y, float z, float weight = GOWeight::Default);
GOPoint(glm::vec3 position, float weight = GOWeight::Default);
public:
static std::shared_ptr<GOPoint> Add(float x, float y, float z, float weight = GOWeight::Default);
static std::shared_ptr<GOPoint> Add(glm::vec3 position, float weight = GOWeight::Default);
virtual ~GOPoint() = default;
static std::shared_ptr<GOPoint> Get(const uint32_t& id);
static std::vector<std::shared_ptr<GOPoint>> GetAll();
inline glm::vec3 GetPosition() const { return m_Position; }
inline void SetPosition(glm::vec3 position) { m_Position = position; InitGLObject(); }
inline float X() const { return m_Position.x; }
inline float Y() const { return m_Position.y; }
inline float Z() const { return m_Position.z; }
inline void SetX(float x) { m_Position.x = x; InitGLObject(); }
inline void SetY(float y) { m_Position.y = y; InitGLObject(); }
inline void SetZ(float z) { m_Position.z = z; InitGLObject(); }
inline void SetWeight(float weight) { m_Weight = weight; InitGLObject(); }
inline void Transform(const glm::mat4x4& transformMat) /* override */ {
m_Position = transformMat * glm::vec4(m_Position, 1.0f);
InitGLObject();
}
inline void SetValueFrom(const std::shared_ptr<GOPrimitive>& ptrGO) /* override */ {
auto ptrPoint = std::dynamic_pointer_cast<GOPoint>(ptrGO);
if (ptrPoint != nullptr)
{
SetPosition(ptrPoint->GetPosition());
InitGLObject();
return;
}
AIAC_ERROR("Cannot set value from different type of primitive; The type is {}", ptrGO->GetType());
}
void InitGLObject();
operator glm::vec3() const { return m_Position; }
public:
inline float DistanceTo(const GOPoint& point) const {
return glm::distance(m_Position, point.m_Position);
}
private:
glm::vec3 m_Position;
friend class GOPrimitive;
friend class GOLine;
friend class GOCircle;
friend class GOCylinder;
friend class GOPolyline;
friend class GOTriangle;
friend class GOMesh;
friend class GOText;
};
class GOLine : public GOPrimitive
{
private:
GOLine();
GOLine(GOPoint p1, GOPoint p2, float weight = GOWeight::Default);
public:
static std::shared_ptr<GOLine> Add();
static std::shared_ptr<GOLine> Add(GOPoint p1, GOPoint p2, float weight = GOWeight::Default);
virtual ~GOLine() = default;
static std::shared_ptr<GOLine> Get(const uint32_t& id);
static std::vector<std::shared_ptr<GOLine>> GetAll();
inline GOPoint GetPStart() const { return m_PStart; }
inline GOPoint GetPEnd() const { return m_PEnd; }
inline float GetLength() const { return glm::distance(m_PStart.GetPosition(), m_PEnd.GetPosition()); }
inline void ExtendFromStart(float length) { m_PStart.SetPosition(m_PStart.GetPosition() - glm::normalize(m_PEnd.GetPosition() - m_PStart.GetPosition()) * length); InitGLObject(); }
inline void ExtendFromEnd(float length) { m_PEnd.SetPosition(m_PEnd.GetPosition() + glm::normalize(m_PEnd.GetPosition() - m_PStart.GetPosition()) * length); InitGLObject(); }
inline void ExtendBothEnds(float length) { ExtendFromStart(length/2); ExtendFromEnd(length/2); }
inline glm::vec3 GetMidPointValues() const { return (m_PStart.GetPosition() + m_PEnd.GetPosition()) / 2.0f; }
inline GOPoint GetMidPoint() const { return GOPoint(GetMidPointValues()); }
inline glm::vec3 GetNormalValues() const { return glm::normalize(glm::cross(m_PEnd.GetPosition() - m_PStart.GetPosition(), glm::vec3(0, 0, 1))); }
inline void SetPStart(GOPoint pStart) { m_PStart = pStart; InitGLObject(); }
inline void SetPEnd(GOPoint pEnd) { m_PEnd = pEnd; InitGLObject(); }
inline void SetPts(GOPoint pStart, GOPoint pEnd) { m_PStart = pStart; m_PEnd = pEnd; InitGLObject(); }
float ComputeAngle(std::shared_ptr<GOLine> ptrGO2);
float ComputeSignedAngle(std::shared_ptr<GOLine> ptrGO2);
inline void Transform(const glm::mat4x4& transformMat) /* override */ {
m_PStart.Transform(transformMat);
m_PEnd.Transform(transformMat);
InitGLObject();
}
inline void Translate(const glm::vec3& translation) /* override */ {
m_PStart.SetPosition(m_PStart.GetPosition() + translation);
m_PEnd.SetPosition(m_PEnd.GetPosition() + translation);
InitGLObject();
}
inline void SetValueFrom(const std::shared_ptr<GOPrimitive>& ptrGO) /* override */ {
auto ptrLine = std::dynamic_pointer_cast<GOLine>(ptrGO);
if (ptrLine != nullptr)
{
SetPts(ptrLine->GetPStart(), ptrLine->GetPEnd());
InitGLObject();
return;
}
AIAC_ERROR("Cannot set value from different type of primitive; The type is {}", ptrGO->GetType());
}
void InitGLObject();
private:
GOPoint m_PStart;
GOPoint m_PEnd;
friend class GOPoint;
};
class GOCircle : public GOPrimitive
{
private:
GOCircle(GOPoint center, float radius);
GOCircle(GOPoint center, glm::vec3 normal, float radius);
public:
static std::shared_ptr<GOCircle> Add(GOPoint center, float radius);
static std::shared_ptr<GOCircle> Add(GOPoint center, glm::vec3 normal, float radius);
virtual ~GOCircle() = default;
glm::vec3 ClosestPointToPoint(glm::vec3 point);
public:
inline static glm::vec3 ClosestPointToCircle(const glm::vec3& point, const glm::vec3& circleCenter, const glm::vec3& circleNormal, float circleRadius) {
glm::vec3 normalizedCircleNormal = glm::normalize(circleNormal);
glm::vec3 circleToPoint = point - circleCenter;
glm::vec3 projectionOntoPlane = circleToPoint - normalizedCircleNormal * glm::dot(circleToPoint, normalizedCircleNormal);
glm::vec3 closestPointOnCircumference = circleCenter + glm::normalize(projectionOntoPlane) * circleRadius;
return closestPointOnCircumference;
}
inline static float ClosestDistanceFromLineToCircle(
std::shared_ptr<GOLine> ptrLine,
const glm::vec3& circleCenter,
float circleRadius)
{
glm::vec3 lineStart = ptrLine->GetPStart().GetPosition();
glm::vec3 lineEnd = ptrLine->GetPEnd().GetPosition();
glm::vec3 lineDirection = glm::normalize(lineEnd - lineStart);
glm::vec3 lineToCircle = circleCenter - lineStart;
glm::vec3 projectionOntoLine = lineStart + lineDirection * glm::dot(lineToCircle, lineDirection);
float distance = glm::distance(circleCenter, projectionOntoLine) - circleRadius;
return distance;
}
inline static std::pair<float, std::pair<glm::vec3, glm::vec3>> ClosestDistanceFromSegmentToCircle(
std::shared_ptr<GOLine> ptrLine,
const glm::vec3& circleCenter,
float circleRadius)
{
glm::vec3 lineStart = ptrLine->GetPStart().GetPosition();
glm::vec3 lineEnd = ptrLine->GetPEnd().GetPosition();
glm::vec3 lineDirection = glm::normalize(lineEnd - lineStart);
glm::vec3 lineToCircleCenter = circleCenter - lineStart;
// Project circleCenter onto line, clamping to the segment
float t = glm::dot(lineToCircleCenter, lineDirection);
t = std::max(0.0f, std::min(t, glm::length(lineEnd - lineStart)));
glm::vec3 closestPointOnLine = lineStart + t * lineDirection;
// Calculate the direction from the circle center to the closest point on the line
glm::vec3 directionToClosestPoint = closestPointOnLine - circleCenter;
float distanceToLine = glm::length(directionToClosestPoint);
glm::vec3 closestPointOnCircle;
if (distanceToLine < circleRadius) {
// The line segment intersects the circle, set the closest point on the circle to the closest point on the line
closestPointOnCircle = closestPointOnLine;
} else {
// Calculate the closest point on the circle to the line segment
glm::vec3 direction = glm::normalize(directionToClosestPoint);
closestPointOnCircle = circleCenter + direction * circleRadius;
}
// Calculate the final distance from the line segment to the circle
float finalDistance = glm::max(0.0f, distanceToLine - circleRadius);
return std::make_pair(finalDistance, std::make_pair(closestPointOnLine, closestPointOnCircle));
}
public:
static std::shared_ptr<GOCircle> Get(const uint32_t& id);
static std::vector<std::shared_ptr<GOCircle>> GetAll();
inline glm::vec3 GetNormal() const { return m_Normal; }
inline GOPoint GetCenter() const { return m_Center; }
inline float GetRadius() const { return m_Radius; }
inline glm::vec4 GetEdgeColor() const { return m_EdgeColor; }
inline void SetNormal(glm::vec3 normal) { m_Normal = normal; InitGLObject(); }
inline void SetCenter(GOPoint center) { m_Center = center; InitGLObject(); }
inline void SetRadius(float radius) { m_Radius = radius; InitGLObject(); }
inline void SetEdgeColor(glm::vec4 edgeColor) { m_EdgeColor = edgeColor; InitGLObject(); }
inline void Transform(const glm::mat4x4& transformMat) /* override */ {
m_Center.Transform(transformMat);
m_Normal = glm::normalize(glm::vec3(transformMat * glm::vec4(m_Normal, 0.0f)));
InitGLObject();
}
inline void SetValueFrom(const std::shared_ptr<GOPrimitive>& ptrGO) /* override */ {
auto ptrCircle = std::dynamic_pointer_cast<GOCircle>(ptrGO);
if (ptrCircle)
{
SetCenter(ptrCircle->GetCenter());
SetNormal(ptrCircle->GetNormal());
SetRadius(ptrCircle->GetRadius());
SetEdgeColor(ptrCircle->GetEdgeColor());
InitGLObject();
return;
}
AIAC_ERROR("Cannot set value from different type of primitive; The type is {}", ptrGO->GetType());
}
void InitGLObject();
private:
GOPoint m_Center;
glm::vec3 m_Normal = glm::vec3(0, 0, 1);
glm::vec4 m_EdgeColor = glm::vec4(1, 0, 0, 1);
float m_Radius;
friend class GOPoint;
};
class GOCylinder : public GOPrimitive
{
private:
GOCylinder(GOPoint p1, GOPoint p2, float radius);
public:
static std::shared_ptr<GOCylinder> Add(GOPoint p1, GOPoint p2, float radius);
virtual ~GOCylinder() = default;
static std::shared_ptr<GOCylinder> Get(const uint32_t& id);
static std::vector<std::shared_ptr<GOCylinder>> GetAll();
GOPoint GetPStart() const { return m_PStart; }
GOPoint GetPEnd() const { return m_PEnd; }
float GetRadius() const { return m_Radius; }
glm::vec4 GetEdgeColor() const { return m_EdgeColor; }
void SetPStart(GOPoint pStart) { m_PStart = pStart; InitGLObject(); }
void SetPEnd(GOPoint pEnd) { m_PEnd = pEnd; InitGLObject(); }
void SetRadius(float radius) { m_Radius = radius; InitGLObject(); }
void SetEdgeColor(glm::vec4 edgeColor) { m_EdgeColor = edgeColor; InitGLObject(); }
inline void Transform(const glm::mat4x4& transformMat) /* override */ {
m_PStart.Transform(transformMat);
m_PEnd.Transform(transformMat);
InitGLObject();
}
inline void SetValueFrom(const std::shared_ptr<GOPrimitive>& ptrGO) /* override */ {
auto ptrCylinder = std::dynamic_pointer_cast<GOCylinder>(ptrGO);
if (ptrCylinder)
{
SetPStart(ptrCylinder->GetPStart());
SetPEnd(ptrCylinder->GetPEnd());
SetRadius(ptrCylinder->GetRadius());
SetEdgeColor(ptrCylinder->GetEdgeColor());
InitGLObject();
return;
}
AIAC_ERROR("Cannot set value from different type of primitive; The type is {}", ptrGO->GetType());
}
void InitGLObject();
private:
GOPoint m_PStart;
GOPoint m_PEnd;
float m_Radius;
glm::vec4 m_EdgeColor = glm::vec4(0, 1, 1, 1);
friend class GOPoint;
};
// FIXME: the polyline is not renderered
class GOPolyline : public GOPrimitive
{
private:
GOPolyline();
GOPolyline(std::vector<GOPoint> points, bool isClosed = false, float weight = GOWeight::Default);
public:
static std::shared_ptr<GOPolyline> Add();
static std::shared_ptr<GOPolyline> Add(std::vector<GOPoint> points, bool isClosed = false, float weight = GOWeight::Default);
static std::shared_ptr<GOPolyline> Add(std::vector<glm::vec3> points, bool isClosed = false, float weight = GOWeight::Default);
virtual ~GOPolyline() = default;
static std::shared_ptr<GOPolyline> Get(const uint32_t& id);
static std::vector<std::shared_ptr<GOPolyline>> GetAll();
inline const std::vector<GOPoint> &GetPoints() const { return m_Points; }
inline void SetPoints(std::vector<glm::vec3> points) {
m_Points.clear();
for (auto& point : points) {
m_Points.push_back(GOPoint(point));
}
InitGLObject();
}
inline void SetPoints(std::vector<GOPoint> points) { m_Points = points; InitGLObject(); }
inline void SetClosed(bool isClosed) { m_IsClosed = isClosed; InitGLObject(); }
inline bool IsClosed() const { return m_IsClosed; }
inline void SetWeight(float weight) { m_Weight = weight; InitGLObject(); }
inline void Transform(const glm::mat4x4& transformMat) /* override */ {
for (auto& point : m_Points) {
point.Transform(transformMat);
}
InitGLObject();
}
GOPrimitive operator* (const glm::mat4x4& transformMat)
{
GOPolyline polyline = *this;
polyline.Transform(transformMat);
return polyline;
}
void InitGLObject();
private:
std::vector<GOPoint> m_Points;
bool m_IsClosed = true;
float m_Weight = GOWeight::Default;
friend class GOPoint;
};
class GOTriangle : public GOPrimitive
{
private:
GOTriangle(GOPoint p1, GOPoint p2, GOPoint p3);
public:
static std::shared_ptr<GOTriangle> Add(GOPoint p1, GOPoint p2, GOPoint p3);
virtual ~GOTriangle() = default;
static std::shared_ptr<GOTriangle> Get(const uint32_t& id);
static std::vector<std::shared_ptr<GOTriangle>> GetAll();
const std::vector<glm::vec3> GetVertices() const {
return std::vector<glm::vec3>{m_P1.GetPosition(), m_P2.GetPosition(), m_P3.GetPosition()};
}
inline void SetWeight(float weight) { m_Weight = weight; InitGLObject(); }
inline void Transform(const glm::mat4x4& transformMat) /* override */ {
m_P1.Transform(transformMat);
m_P2.Transform(transformMat);
m_P3.Transform(transformMat);
InitGLObject();
}
GOPrimitive operator* (const glm::mat4x4& transformMat)
{
GOTriangle triangle = *this;
triangle.Transform(transformMat);
return triangle;
}
void InitGLObject();
private:
GOPoint m_P1;
GOPoint m_P2;
GOPoint m_P3;
float m_Weight = GOWeight::Default;
friend class GOPoint;
};
class GOMesh : public GOPrimitive
{
private:
GOMesh();
GOMesh(std::vector<glm::vec3> vertices, std::vector<uint32_t> indices,
std::vector<glm::vec3> normals = std::vector<glm::vec3>(),
std::vector<glm::vec4> colors = std::vector<glm::vec4>());
public:
static std::shared_ptr<GOMesh> Add();
static std::shared_ptr<GOMesh> Add(std::vector<glm::vec3> vertices, std::vector<uint32_t> indices);
static std::shared_ptr<GOMesh> LoadPly(std::string);
virtual ~GOMesh() = default;
static std::shared_ptr<GOMesh> Get(const uint32_t& id);
static std::vector<std::shared_ptr<GOMesh>> GetAll();
const std::vector<glm::vec3> GetVertices() const { return m_Vertices; }
const std::vector<uint32_t> GetIndices() const { return m_Indices; }
const std::vector<glm::vec3> GetNormals() const { return m_Normals; }
const std::vector<glm::vec4> GetColors() const { return m_Colors; }
void SetColors(std::vector<glm::vec4> colors) {
m_IsUsingUniformColor = false;
m_Colors = colors;
InitGLObject();
}
void SetColor(glm::vec4 color) {
m_IsUsingUniformColor = true;
m_UniformColor = color;
m_Colors = std::vector<glm::vec4>(m_Vertices.size(), m_UniformColor);
InitGLObject();
}
void SetVertices(std::vector<glm::vec3> vertices) {
if(m_IsUsingUniformColor && m_Vertices.size() != vertices.size()){
SetColor(m_UniformColor);
}
m_Vertices = vertices;
if(m_IsUsingUniformColor){
SetColor(m_UniformColor);
}
InitGLObject();
}
void SetIndices(std::vector<uint32_t> indices) { m_Indices = indices; InitGLObject(); }
void SetNormals(std::vector<glm::vec3> normals) { m_Normals = normals; InitGLObject(); }
void InitGLObject();
inline void Transform(const glm::mat4x4& transformMat) /* override */ {
// vertices
for (auto& vertex : m_Vertices) {
vertex = glm::vec3(transformMat * glm::vec4(vertex, 1.0f));
}
// normals
for (auto& normal : m_Normals) {
normal = glm::normalize(glm::vec3(transformMat * glm::vec4(normal, 0.0f)));
}
InitGLObject();
}
GOPrimitive operator* (const glm::mat4x4& transformMat)
{
GOMesh mesh = *this;
mesh.Transform(transformMat);
return mesh;
}
private:
std::vector<glm::vec3> m_Vertices;
std::vector<uint32_t> m_Indices;
std::vector<glm::vec3> m_Normals;
std::vector<glm::vec4> m_Colors;
glm::vec4 m_UniformColor = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
bool m_IsUsingUniformColor = true;
friend class GOPoint;
};
class GOText : public GOPrimitive
{
private:
GOText();
GOText(std::string text, GOPoint anchor, double size);
public:
static std::shared_ptr<GOText> Add();
static std::shared_ptr<GOText> Add(std::string text, GOPoint anchor, double size = GOTextSize::Default);
virtual ~GOText() = default;
static std::shared_ptr<GOText> Get(const uint32_t& id);
static std::vector<std::shared_ptr<GOText>> GetAll();
inline const std::string GetText() const { return m_Text; }
inline const GOPoint GetAnchor() const { return m_Anchor; }
inline const double GetTextSize() const { return m_Size; }
inline void SetText(const std::string text) { m_Text = text; InitGLObject(); }
inline void SetAnchor(const GOPoint anchor) { m_Anchor = anchor; InitGLObject(); }
inline void SetAnchor(const glm::vec3 anchor) { m_Anchor.SetPosition(anchor); InitGLObject(); }
inline void SetTextSize(const double size) { m_Size = size; InitGLObject(); }
inline void Transform(const glm::mat4x4& transformMat) /* override */ { m_Anchor.Transform(transformMat); }
inline void SetValueFrom(const std::shared_ptr<GOPrimitive>& ptrGO) /* override */ {
auto ptrPoint = std::dynamic_pointer_cast<GOText>(ptrGO);
if (ptrPoint != nullptr)
{
SetText(ptrPoint->GetText());
SetAnchor(ptrPoint->GetAnchor());
SetTextSize(ptrPoint->GetTextSize());
InitGLObject();
return;
}
AIAC_ERROR("Cannot set value from different type of primitive; The type is {}", ptrGO->GetType());
}
GOPrimitive operator* (const glm::mat4x4& transformMat)
{
GOText text = *this;
text.Transform(transformMat);
return text;
}
private:
GOPoint m_Anchor;
std::string m_Text;
double m_Size;
friend class GOPoint;
};
}