Shape类只是单纯的形状数据,并不能用具真正的绘制,真正的绘制工作是Gizmo类去做的。该类只是作为Gizmo的一个成员去使用的。Shape的函数只是提供了加工数据的,然后把加工后的数据存下来。不多哔哔了,直接贴代码。原理有空了再详细写。
Shape.h
#pragma once
#define VSFRONT 0 //面前
#define VSBACK 1 //面后
#define VSPLANAR 2 //面上
#define VSCLIPPED 0 //剪裁
#define VSCULLED 1 //刨除
#define VSCONTAIN 2 //包含
#define EPSILON_E3 0.00001
//线段类
class GLLine
{
private:
public:
Vector2 m_vcOrig; //源点|起点
Vector2 m_vcDir; //单位方向长度
float m_len; //向量长度|模
//通过起点和终点获取线段
void Set(Vector2 &vcOrig, Vector2 &vcEnd);
//通过点和方向获取线段
void Set(Vector2 &vcOrig, Vector2 &vcDir, float len);
GLLine(Vector2 &vcOrig, Vector2 &vcEnd);
Vector2 getEnd()const;
GLLine() {};
~GLLine() {};
};
//圆
class GLCircle
{
private:
public:
float radius;
Vector2 center;
void Set(Vector2 pos, float r);
GLCircle(Vector2 pos, float r);
GLCircle() {}
~GLCircle() {}
};
//多边形类
class GLPolygon
{
private:
public:
GLLine *m_line;
int m_lineNum;
GLPolygon(GLLine the_lines[], int the_lineNum);
GLPolygon(Vector2 the_points[], int the_pointNum);
void Set(GLLine lines[], int lineNum);
void Set(Vector2 points[], int pointNum);
Vector2 m_vcMin;
Vector2 m_vcMax;
GLPolygon() { m_line = nullptr; }
~GLPolygon() {}
};
class GLAABB
{
public:
Vector2 m_vcMin; //最小边界
Vector2 m_vcMax; //最大边界
Vector2 m_vcCenter; // 中心
//通过最大点,最小点获取Aabb
void Set(Vector2 &vcMin, Vector2 &vcMax);
//通过长宽高和位置获取Aabb
void Set(float width, float height, Vector2 ¢erPos);
//
void Set(Vector2 aabb[]);
GLAABB(float wid, float hei, Vector2 center);
GLAABB() {}
~GLAABB() {}
};
class GLRay
{
public:
Vector2 m_vcOrig; //源点
Vector2 m_vcDir; //单位方向
//通过点和方向获取射线
void Set(Vector2 &vcOrig, Vector2 &vcDir);
GLRay() {}
~GLRay() {}
};
class GLPlane
{
public:
Vector3D m_vcN; //平面法向量
Vector3D m_vcPoint; // 平面上的点
float m_fD; // 到原点的距离(ax+by+cz+d=0,-d)
void Set(Vector3D &vcN, float fD);//通过法线和常量d获取平面
void Set(Vector3D &vcN, Vector3D &vcP);//通过法线,点获取平面
void Set(Vector3D &v0, Vector3D &v1, Vector3D &v2);//通过三个点获取平面
/*点和平面的位置关系(VSFRONT VSBACK VSPLANAR)
算法描述
用平面上点和vcPoint组成向量和平面向量做点积,根据值的符号判断位置*/
int Classify(Vector3D &vcPoint);//判断点是不是在平面上
GLPlane(){}
~GLPlane(){}
};
class GLPoint
{
public:
Vector3D m_center;
void setCenter(Vector3D ¢er);
int Cull(GLPlane *pPlanes, int nNumPlanes);//判断点是不是在平面里
GLPoint() {}
~GLPoint() {}
};
//球类
class GLSphere
{
public:
Vector3D m_center;
float m_radius;
public:
GLSphere(Vector3D ¢er,float radius);
void Set(Vector3D center, float radius);//通过中心点和半径获取球
int Cull(GLPlane *pPlanes, int nNumPlanes);//判断多面体和球位置关系(VSCULLED,VSCLIPPED,VSVISIBLE)
bool IsPointIn(Vector3D &point);//判断点在球内
bool Intersects(Vector3D &v1, Vector3D &v2);//是否与线段相交
GLSphere() {}
~GLSphere() {}
};
class GLAABB3D
{
public:
Vector3D m_vcMin; //最小边界
Vector3D m_vcMax; //最大边界
Vector3D m_vcCenter; // 中心
Vector3D CORNERPOINT[8];//八个顶点
float length;
float width;
float height;
GLAABB3D(Vector3D &vcMin, Vector3D &vcMax);
GLAABB3D(float length, float width, float height, Vector3D &position);
void Set(Vector3D &vcMin, Vector3D &vcMax);//通过最大点,最小点获取Aabb
void Set(float length, float width, float height, Vector3D &position);//通过长宽高和位置获取Aabb
void Set(Vector3D everyPoint[]);
bool IsPointIn(Vector3D &point);//判断点在AABB内
int Cull(GLPlane *pPlanes, int nNumPlanes);//判断多面体和AABB位置关系(VSCULLED,VSCLIPPED,VSVISIBLE)
GLAABB3D() {}
~GLAABB3D() {}
};
class GLLine3D
{
private:
public:
Vector3D m_vcOrig; //源点|起点
Vector3D m_vcDir; //单位方向长度
float m_len; //向量长度|模
void Set(Vector3D &vcOrig, Vector3D &vcEnd); //通过起点和终点获取线段
//通过点和方向获取线段
void Set(Vector3D &vcOrig, Vector3D &vcDir, float len);
GLLine3D(Vector3D &vcOrig, Vector3D &vcEnd);
Vector3D getEnd()const;
GLLine3D() {};
~GLLine3D() {};
};
class GLRay3D
{
public:
Vector3D m_vcOrig; //源点
Vector3D m_vcDir; //单位方向
void Set(Vector3D &vcOrig, Vector3D &vcDir);//通过点和方向获取射线
bool Intersects(GLSphere &sphere_a, Vector3D &hitPoint);
bool Intersects(GLLine3D &line_a, Vector3D &hitPoint);
bool Intersects(GLPlane & plane_a, int size, Vector3D & hitPoint);
GLRay3D() {}
~GLRay3D() {}
};
class GLTrianglePlane:public GLPlane
{
public:
Vector3D m_v0, m_v1, m_v2;
Vector3D m_vertex[3];
void set(Vector3D v0, Vector3D v1, Vector3D v2);
bool IsPointIn(Vector3D & point);
};
Shape.cpp
#include "Engine.h"
//线段
GLLine::GLLine(Vector2 &vcOrig, Vector2 &vcEnd)
{
m_vcOrig = vcOrig;
m_vcDir = (vcEnd - vcOrig).Normalize();
m_len = (vcEnd - vcOrig).length();
}
void GLLine::Set(Vector2 &vcOrig, Vector2 &vcEnd)
{
m_vcOrig = vcOrig;
m_vcDir =(vcEnd - vcOrig).Normalize();
m_len = (vcEnd - vcOrig).length();
}
void GLLine::Set(Vector2 &vcOrig, Vector2 &vcDir, float len)
{
m_vcOrig = vcOrig;
m_vcDir = vcDir;
m_len = len;
}
Vector2 GLLine::getEnd() const
{
return Vector2(m_vcOrig.x + m_len*m_vcDir.x, m_vcOrig.y + m_len*m_vcDir.y);
}
//3D空间中的线
GLLine3D::GLLine3D(Vector3D &vcOrig, Vector3D &vcEnd)
{
m_vcOrig = vcOrig;
m_vcDir = (vcEnd - vcOrig).Normalize();
m_len = (vcEnd - vcOrig).length();
}
void GLLine3D::Set(Vector3D &vcOrig, Vector3D &vcEnd)
{
m_vcOrig = vcOrig;
m_vcDir = (vcEnd - vcOrig).Normalize();
m_len = (vcEnd - vcOrig).length();
}
void GLLine3D::Set(Vector3D &vcOrig, Vector3D &vcDir, float len)
{
m_vcOrig = vcOrig;
m_vcDir = vcDir;
m_len = len;
}
Vector3D GLLine3D::getEnd()const
{
return Vector3D(m_vcOrig.x + m_len*m_vcDir.x, m_vcOrig.y + m_len*m_vcDir.y,m_vcOrig.z+m_len*m_vcDir.z);
}
//圆形
GLCircle::GLCircle(Vector2 pos, float r)
{
this->center = pos;
this->radius = r;
}
void GLCircle::Set(Vector2 pos, float r)
{
this->center = pos;
this->radius = r;
}
//多边形
GLPolygon::GLPolygon(GLLine lines[], int lineNum)
{
m_line = new GLLine[lineNum];
memcpy(m_line, lines, sizeof(GLLine)*lineNum);
this->m_lineNum = lineNum;
}
GLPolygon::GLPolygon(Vector2 points[], int pointNum)
{
m_lineNum = pointNum;
m_line = new GLLine[pointNum];
for (int i = 0;i < pointNum;i++)
{
m_line[i].Set(points[i], points[(i + 1) % pointNum]);
}
m_vcMin.x = points[0].x;
m_vcMin.y = points[0].y;
m_vcMax.x = points[0].x;
m_vcMax.y = points[0].y;
for (int i = 1; i points[i].x)
swap(m_vcMin.x, points[i].x);
if (m_vcMin.y > points[i].y)
swap(m_vcMin.y, points[i].y);
if (m_vcMax.x < points[i].x)
swap(m_vcMax.x, points[i].x);
if (m_vcMax.y < points[i].y)
swap(m_vcMax.y, points[i].y);
}
}
void GLPolygon::Set(GLLine lines[], int lineNum)
{
delete[]m_line;
m_line = new GLLine[lineNum];
memcpy(m_line,lines,sizeof(GLLine)*lineNum);
this->m_lineNum = lineNum;
}
void GLPolygon::Set(Vector2 points[], int pointNum)
{
delete[]m_line;
m_lineNum = pointNum;
m_line = new GLLine[pointNum];
for (int i = 0;i < pointNum;i++)
{
m_line[i].Set(points[i], points[(i+1)% pointNum]);
}
}
GLAABB::GLAABB(float wid, float hei, Vector2 center)
{
Set(wid, hei, center);
}
void GLAABB::Set(Vector2 &vcMin, Vector2 &vcMax)
{
this->m_vcMin = vcMin;
this->m_vcMax = vcMax;
this->m_vcCenter = m_vcMin+(vcMax - vcMin) / 2;
}
void GLAABB::Set(float width, float height, Vector2 ¢erPos)
{
this->m_vcCenter = centerPos;
//算最小点
this->m_vcMin.x= centerPos.x-width*0.5;
this->m_vcMin.y = centerPos.y-height*0.5;
//算最大点
this->m_vcMax.x = centerPos.x+width*0.5;
this->m_vcMax.y = centerPos.y+height*0.5;
}
void GLAABB::Set(Vector2 vec[])
{
m_vcMin =Vector2(9999,9999);
m_vcMax= Vector2(-9999,-9999);
for (int i = 0; i < 4; i++)
{
if (m_vcMin.x > vec[i].x){m_vcMin.x=vec[i].x;}
if (m_vcMin.y > vec[i].y){m_vcMin.y=vec[i].y;}
if (m_vcMax.x < vec[i].x){m_vcMax.x=vec[i].x;}
if (m_vcMax.y < vec[i].y){m_vcMax.y=vec[i].y;}
}
}
void GLRay::Set(Vector2 &vcOrig, Vector2 &vcDir)
{
this->m_vcOrig = vcOrig;
this->m_vcDir = vcDir.Normalize();
}
void GLPlane::Set(Vector3D &vcN, float fD)
{
float len=vcN.length();
m_vcN.x= vcN.x /= len;
m_vcN.y= vcN.y/= len;
m_vcN.z= vcN.z/= len;
m_fD=fD/= len;
}
void GLPlane::Set(Vector3D &vcN,Vector3D &vcP)//法向量和一个点
{
m_vcN = vcN.Normalize();
m_fD = -m_vcN.dot(vcP);//面上的法向量点乘一个点
m_vcPoint = vcP;
}
void GLPlane::Set(Vector3D &v0,Vector3D &v1,Vector3D &v2)
{
Vector3D vcEdge1 = v1 - v0;
Vector3D vcEdge2 = v2 - v0;
m_vcN = vcEdge1.cross(vcEdge2);
m_vcN.normalize();
m_fD = -m_vcN.dot(v0);
m_vcPoint = v0;
}
int GLPlane::Classify(Vector3D &vcPoint)
{
float len = m_vcN.dot(m_vcPoint) + m_fD;
if (len > 0)
{
return VSPLANAR;
}
if (len < 0)
{
return VSBACK;
}
return VSPLANAR;
}
void GLPoint::setCenter(Vector3D ¢er)
{
m_center = center;
}
int GLPoint::Cull(GLPlane *pPlanes, int nNumPlanes)
{
for (int i = 0;i < nNumPlanes;++i)
{
float f = m_center.dot(pPlanes[i].m_vcN)+pPlanes[i].m_fD;
/*if (f >0)
return VSFRONT;*/
if (f m_center - v2;
if (d2.length2q() m_radius*this->m_radius)
return true;
//延长线
float l = (v2 - v1).length2q();
float m = d1.length2q() - s*s;
if (m m_radius*this->m_radius&&l > s*s)
return true;
return false;
}
GLAABB3D::GLAABB3D(Vector3D &vcMin, Vector3D &vcMax)
{
Set(vcMin, vcMax);
}
GLAABB3D::GLAABB3D(float length, float width, float height, Vector3D &position)
{
Set(length, width, height, position);
}
void GLAABB3D::Set(Vector3D &vcMin, Vector3D &vcMax)
{
m_vcMin = vcMin;
m_vcMax = vcMax;
this->length = fabs(vcMax.x - vcMin.x);
this->height = fabs( vcMax.y - vcMin.y);
this->width = fabs(vcMax.z - vcMin.z);
CORNERPOINT[0] = Vector3D(vcMin.x, vcMin.y, vcMin.z);
CORNERPOINT[1] = Vector3D(vcMin.x, vcMin.y, vcMax.z);
CORNERPOINT[2] = Vector3D(vcMin.x, vcMax.y, vcMin.z);
CORNERPOINT[3] = Vector3D(vcMax.x, vcMin.y, vcMin.z);
CORNERPOINT[4] = Vector3D(vcMax.x, vcMax.y, vcMin.z);
CORNERPOINT[5] = Vector3D(vcMax.x, vcMin.y, vcMax.z);
CORNERPOINT[6] = Vector3D(vcMin.x, vcMax.y, vcMax.z);
CORNERPOINT[7] = Vector3D(vcMax.x, vcMax.y, vcMax.z);
m_vcCenter = (vcMax + vcMin) / 2;
}
void GLAABB3D::Set(float length, float width, float height, Vector3D &position)
{
//长:X - 宽:Z - 高:Y;
//以中心点画AABB
m_vcCenter = position;
m_vcMin.x = position.x - width;
m_vcMin.y = position.y /*- height*/;
m_vcMin.z = position.z - width;
m_vcMax.x = position.x +width;
m_vcMax.y = position.y + height;
m_vcMax.z = position.z + width;
this->length = length;
this->width = width;
this->height = height;
CORNERPOINT[0] = Vector3D(-length*0.5, -height*0.5, -width*0.5);
CORNERPOINT[1] = Vector3D(-length*0.5, -height*0.5, +width*0.5);
CORNERPOINT[2] = Vector3D(-length*0.5, +height*0.5, -width*0.5);
CORNERPOINT[3] = Vector3D(+length*0.5, -height*0.5, -width*0.5);
CORNERPOINT[4] = Vector3D(-length*0.5, +height*0.5, +width*0.5);
CORNERPOINT[5] = Vector3D(+length*0.5, +height*0.5, -width*0.5);
CORNERPOINT[6] = Vector3D(+length*0.5, -height*0.5, +width*0.5);
CORNERPOINT[7] = Vector3D(+length*0.5, +height*0.5, +width*0.5);
m_vcCenter = (m_vcMax + m_vcMin) / 2;
}
void GLAABB3D::Set(Vector3D vec[])
{
m_vcMin = Vector3D(99999, 99999,99999);
m_vcMax = Vector3D(-99999, -99999,-99999);
for (int i = 0; i vec[i].x)
m_vcMin.x = vec[i].x;
if (m_vcMin.y > vec[i].y)
m_vcMin.y = vec[i].y;
if( m_vcMin.z>=vec[i].z)
m_vcMin.z = vec[i].z;
if (m_vcMax.x < vec[i].x)
m_vcMax.x = vec[i].x;
if (m_vcMax.y < vec[i].y)
m_vcMax.y = vec[i].y;
if (m_vcMax.z < vec[i].z)
m_vcMax.z = vec[i].z;
}
this->length = fabs(m_vcMax.x - m_vcMin.x);
this->height = fabs(m_vcMax.y - m_vcMin.y);
this->width = fabs(m_vcMax.z - m_vcMin.z);
m_vcCenter = (m_vcMax + m_vcMin) / 2;
}
bool GLAABB3D::IsPointIn(Vector3D &point)
{
if (point.x>m_vcMin.x&&point.xm_vcMin.y&&point.ym_vcMin.z&&point.z= 0.0f)
{
vcMin.x = m_vcMin.x;
vcMax.x = m_vcMax.x;
}
else
{
vcMin.x = m_vcMax.x;
vcMax.x = m_vcMin.x;
}
// y
if (pPlanes[i].m_vcN.y >= 0.0f)
{
vcMin.y = m_vcMin.y;
vcMax.y = m_vcMax.y;
}
else {
vcMin.y = m_vcMax.y;
vcMax.y = m_vcMin.y;
}
// z
if (pPlanes[i].m_vcN.z >= 0.0f)
{
vcMin.z = m_vcMin.z;
vcMax.z = m_vcMax.z;
}
else
{
vcMin.z = m_vcMax.z;
vcMax.z = m_vcMin.z;
}
//刨除
if ((pPlanes[i].m_vcN.dot(vcMin) + pPlanes[i].m_fD) > 0.0f)
return VSCULLED;
if ((pPlanes[i].m_vcN.dot(vcMax) + pPlanes[i].m_fD) >= 0.0f)
bIntersects = true;
}
//剪裁
if (bIntersects)
return VSCLIPPED;
//包含
return VSCONTAIN;
}
void GLRay3D::Set(Vector3D&vcOrig,Vector3D &vcDir)
{
m_vcOrig = vcOrig;
m_vcDir = vcDir.Normalize();
}
//射线与线段碰撞
bool GLRay3D::Intersects(GLLine3D &line_a, Vector3D &hitPoint)
{
Vector3D n = m_vcDir.cross(line_a.m_vcDir);
if (fabs(n.length()) < EPSILON_E3)
return false;
float s = ((line_a.m_vcOrig - this->m_vcOrig).cross(line_a.m_vcDir)).dot(n);
s /= n.length()*n.length();
float t = ((this->m_vcOrig - line_a.m_vcOrig).cross(m_vcDir)).dot(-n);
t /= n.length()*n.length();
if (s >= 0 && t >= 0 && t 0.0f)
return false;*/
float Vo = -(plane_a.m_vcN.dot(m_vcOrig) + plane_a.m_fD);
float f = Vo / Vd;
if (f >= 0.0f)
{
hitPoint = m_vcOrig + (m_vcDir * f);
Vector3D d = hitPoint - plane_a.m_vcPoint;
if (fabs(d.x) m_v2 = v2;
m_vertex[0] = v0;
m_vertex[1] = v1;
m_vertex[2] = v2;
//GLPlane::Set(v0, v1, v2);
Set(v0, v1, v2);
}
bool GLTrianglePlane::IsPointIn(Vector3D & point)
{
Vector3D p0 = m_vertex[1] - m_vertex[0];
Vector3D p1 = m_vertex[2] - m_vertex[0];
Vector3D p2 = point - m_vertex[0];
float dot00 = p0.dot(p0);
float dot01 = p0.dot(p1);
float dot02 = p0.dot(p2);
float dot11 = p1.dot(p1);
float dot12 = p1.dot(p2);
float inverDeno = 1.0f / (dot00*dot11 - dot01*dot01);
float u = (dot02*dot11 - dot01*dot12)*inverDeno;
if (u < 0 || u > 1)
{
return false;
}
float v = (dot00*dot12 - dot02*dot01)*inverDeno;
if (v < 0 || v > 1)
{
return false;
}
return u + v
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?