402 lines
9.7 KiB
C++
402 lines
9.7 KiB
C++
#include "include/Engine.h"
|
|
|
|
namespace SE
|
|
{
|
|
|
|
#ifdef TARGET_WIN32
|
|
|
|
VBOObject::VBOObject()
|
|
{
|
|
AssertIfInMainThread();
|
|
|
|
glGenBuffers(1, &Buffer);
|
|
}
|
|
|
|
VBOObject::VBOObject(const VBOObject& c)
|
|
{
|
|
throw ErrorToLog("Copy constructor for VBOObject called\n");
|
|
}
|
|
|
|
VBOObject& VBOObject::operator=(const VBOObject& c)
|
|
{
|
|
throw ErrorToLog("operator= for VBOObject called\n");
|
|
return *this;
|
|
}
|
|
|
|
VBOObject::~VBOObject()
|
|
{
|
|
AssertIfInMainThread();
|
|
|
|
glDeleteBuffers(1, &Buffer);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
TDataTriangleList& TDataTriangleList::operator+=(const TDataTriangleList& dataTriangleList)
|
|
{
|
|
BOOST_FOREACH(auto& i, dataTriangleList.Vec3CoordArr)
|
|
{
|
|
if (Vec3CoordArr.count(i.first) == 0)
|
|
{
|
|
Vec3CoordArr[i.first] = i.second;
|
|
}
|
|
else
|
|
{
|
|
Vec3CoordArr[i.first].insert(Vec3CoordArr[i.first].end(), i.second.begin(), i.second.end());
|
|
}
|
|
}
|
|
|
|
BOOST_FOREACH(auto& i, dataTriangleList.Vec2CoordArr)
|
|
{
|
|
if (Vec2CoordArr.count(i.first) == 0)
|
|
{
|
|
Vec2CoordArr[i.first] = i.second;
|
|
}
|
|
else
|
|
{
|
|
Vec2CoordArr[i.first].insert(Vec2CoordArr[i.first].end(), i.second.begin(), i.second.end());
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
TTriangleListAncestor::TTriangleListAncestor()
|
|
{
|
|
}
|
|
|
|
TTriangleListAncestor::TTriangleListAncestor(const TTriangleListAncestor& c)
|
|
{
|
|
Data = c.Data;
|
|
}
|
|
|
|
TTriangleListAncestor& TTriangleListAncestor::operator=(const TTriangleListAncestor& c)
|
|
{
|
|
Data = c.Data;
|
|
RefreshBuffer();
|
|
return *this;
|
|
}
|
|
|
|
TTriangleListAncestor::TTriangleListAncestor(const TDataTriangleList& dataTriangleList)
|
|
{
|
|
Data = dataTriangleList;
|
|
}
|
|
|
|
TTriangleListAncestor& TTriangleListAncestor::operator=(const TDataTriangleList& dataTriangleList)
|
|
{
|
|
Data = dataTriangleList;
|
|
RefreshBuffer();
|
|
|
|
return *this;
|
|
}
|
|
|
|
TTriangleListAncestor::~TTriangleListAncestor()
|
|
{
|
|
}
|
|
|
|
|
|
#ifdef TARGET_WIN32
|
|
|
|
TTriangleList::TTriangleList()
|
|
: TTriangleListAncestor()
|
|
, NeedPrepareBufferObjects(true)
|
|
, NeedRefreshBuffer(false)
|
|
{
|
|
}
|
|
|
|
TTriangleList::~TTriangleList()
|
|
{
|
|
}
|
|
|
|
void TTriangleList::InnerRefreshBuffer()
|
|
{
|
|
AssertIfInMainThread();
|
|
|
|
if (NeedPrepareBufferObjects && Data.Vec2CoordArr.size() > 0 && Data.Vec3CoordArr.size() > 0)
|
|
{
|
|
|
|
NeedPrepareBufferObjects = false;
|
|
|
|
BOOST_FOREACH(auto& i, Data.Vec2CoordArr)
|
|
{
|
|
if (VertBufferArr[i.first] == std::shared_ptr<VBOObject>())
|
|
{
|
|
VertBufferArr[i.first] = std::shared_ptr<VBOObject>(new VBOObject);
|
|
glBindBuffer(GL_ARRAY_BUFFER, VertBufferArr[i.first]->Buffer);
|
|
|
|
//What to do if buffer becomes empty?
|
|
if (i.second.size() > 0)
|
|
{
|
|
glBufferData(GL_ARRAY_BUFFER, i.second.size() * 8, &i.second[0], GL_STATIC_DRAW);
|
|
}
|
|
else
|
|
{
|
|
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STATIC_DRAW);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
BOOST_FOREACH(auto& i, Data.Vec3CoordArr)
|
|
//for (std::map<std::string, std::vector<vec3> >::iterator i = Data.Vec3CoordArr.begin(); i != Data.Vec3CoordArr.end(); ++i )
|
|
{
|
|
if (VertBufferArr[i.first] == std::shared_ptr<VBOObject>())
|
|
{
|
|
VertBufferArr[i.first] = std::shared_ptr<VBOObject>(new VBOObject);
|
|
glBindBuffer(GL_ARRAY_BUFFER, VertBufferArr[i.first]->Buffer);
|
|
|
|
//What to do if buffer becomes empty?
|
|
if (i.second.size() > 0)
|
|
{
|
|
glBufferData(GL_ARRAY_BUFFER, i.second.size() * 12, &i.second[0], GL_STATIC_DRAW);
|
|
}
|
|
else
|
|
{
|
|
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STATIC_DRAW);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
BOOST_FOREACH(auto& i, Data.Vec2CoordArr)
|
|
{
|
|
glBindBuffer(GL_ARRAY_BUFFER, VertBufferArr[i.first]->Buffer);
|
|
RefreshAttribBuffer2fv(i.first, Data.Vec2CoordArr);
|
|
}
|
|
|
|
BOOST_FOREACH(auto& i, Data.Vec3CoordArr)
|
|
{
|
|
glBindBuffer(GL_ARRAY_BUFFER, VertBufferArr[i.first]->Buffer);
|
|
RefreshAttribBuffer3fv(i.first, Data.Vec3CoordArr);
|
|
}
|
|
|
|
NeedRefreshBuffer = false;
|
|
}
|
|
|
|
|
|
void TTriangleList::RefreshBuffer()
|
|
{
|
|
if (!NeedRefreshBuffer)
|
|
{
|
|
NeedRefreshBuffer = true;
|
|
PerformInMainThreadAsync(boost::bind(&TTriangleList::InnerRefreshBuffer, this));
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
void FillVertexCoordVec(std::vector<vec3>& coordVec, int pos, vec2 posFrom, vec2 posTo)
|
|
{
|
|
vec2 pos1 = posFrom;
|
|
vec2 pos2 = vec2(posFrom.v[0], posTo.v[1]);
|
|
vec2 pos3 = posTo;
|
|
vec2 pos4 = vec2(posTo.v[0], posFrom.v[1]);
|
|
|
|
coordVec[pos] = vec3(pos1, 0);
|
|
coordVec[pos+1] = vec3(pos2, 0);
|
|
coordVec[pos+2] = vec3(pos3, 0);
|
|
coordVec[pos+3] = vec3(pos3, 0);
|
|
coordVec[pos+4] = vec3(pos4, 0);
|
|
coordVec[pos+5] = vec3(pos1, 0);
|
|
|
|
}
|
|
|
|
void FillTexCoordVec(std::vector<vec2>& coordVec, int pos, vec2 texCoordFrom, vec2 texCoordTo)
|
|
{
|
|
vec2 tex1 = texCoordFrom;
|
|
vec2 tex2 = vec2(texCoordFrom.v[0], texCoordTo.v[1]);
|
|
vec2 tex3 = texCoordTo;
|
|
vec2 tex4 = vec2(texCoordTo.v[0], texCoordFrom.v[1]);
|
|
|
|
|
|
coordVec[pos] = tex1;
|
|
coordVec[pos+1] = tex2;
|
|
coordVec[pos+2] = tex3;
|
|
coordVec[pos+3] = tex3;
|
|
coordVec[pos+4] = tex4;
|
|
coordVec[pos+5] = tex1;
|
|
|
|
}
|
|
|
|
void FillVertexCoordVec_4Points(std::vector<vec3>& coordVec, int pos, vec2 pos1, vec2 pos2, vec2 pos3, vec2 pos4)
|
|
{
|
|
coordVec[pos] = vec3(pos1, 0);
|
|
coordVec[pos+1] = vec3(pos2, 0);
|
|
coordVec[pos+2] = vec3(pos3, 0);
|
|
coordVec[pos+3] = vec3(pos3, 0);
|
|
coordVec[pos+4] = vec3(pos4, 0);
|
|
coordVec[pos+5] = vec3(pos1, 0);
|
|
}
|
|
|
|
void FillTexCoordVec_4Points(std::vector<vec2>& coordVec, int pos, vec2 texCoord1, vec2 texCoord2, vec2 texCoord3, vec2 texCoord4)
|
|
{
|
|
coordVec[pos] = texCoord1;
|
|
coordVec[pos+1] = texCoord2;
|
|
coordVec[pos+2] = texCoord3;
|
|
coordVec[pos+3] = texCoord3;
|
|
coordVec[pos+4] = texCoord4;
|
|
coordVec[pos+5] = texCoord1;
|
|
}
|
|
|
|
|
|
std::vector<vec3> MakeVertexCoordVec(vec2 posFrom, vec2 posTo)
|
|
{
|
|
std::vector<vec3> r;
|
|
r.resize(6);
|
|
|
|
FillVertexCoordVec(r, 0, posFrom, posTo);
|
|
|
|
return r;
|
|
}
|
|
|
|
std::vector<vec2> MakeTexCoordVec(vec2 texCoordFrom, vec2 texCoordTo)
|
|
{
|
|
std::vector<vec2> r;
|
|
r.resize(6);
|
|
FillTexCoordVec(r, 0, texCoordFrom, texCoordTo);
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
TDataTriangleList MakeDataTriangleList(vec2 posFrom, vec2 posTo, vec2 texCoordFrom, vec2 texCoordTo)
|
|
{
|
|
TDataTriangleList triangleList;
|
|
|
|
triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB] = MakeVertexCoordVec(posFrom, posTo);
|
|
triangleList.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB] = MakeTexCoordVec(texCoordFrom, texCoordTo);
|
|
|
|
return triangleList;
|
|
}
|
|
|
|
void MoveDataTriangleList(TDataTriangleList& triangleList, vec3 shift)
|
|
{
|
|
if (triangleList.Vec3CoordArr.count(CONST_STRING_POSITION_ATTRIB) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BOOST_FOREACH(auto& i, triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB])
|
|
{
|
|
i += shift;
|
|
}
|
|
}
|
|
|
|
void RotateDataTriangleList(TDataTriangleList& triangleList, const mat3& m)
|
|
{
|
|
if (triangleList.Vec3CoordArr.count(CONST_STRING_POSITION_ATTRIB) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BOOST_FOREACH(vec3& i, triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB])
|
|
{
|
|
i = i * m;
|
|
}
|
|
}
|
|
|
|
void ScaleDataTriangleList(TDataTriangleList& triangleList, float scale)
|
|
{
|
|
if (triangleList.Vec3CoordArr.count(CONST_STRING_POSITION_ATTRIB) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BOOST_FOREACH(vec3& i, triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB])
|
|
{
|
|
i.v[0] *= scale;
|
|
i.v[1] *= scale;
|
|
i.v[2] *= scale;
|
|
}
|
|
}
|
|
|
|
void ScaleDataTriangleList(TDataTriangleList& triangleList, vec3 scaleVec)
|
|
{
|
|
if (triangleList.Vec3CoordArr.count(CONST_STRING_POSITION_ATTRIB) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BOOST_FOREACH(vec3& i, triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB])
|
|
{
|
|
i.v[0] *= scaleVec.v[0];
|
|
i.v[1] *= scaleVec.v[1];
|
|
i.v[2] *= scaleVec.v[2];
|
|
}
|
|
}
|
|
|
|
TDataTriangleList& ClearDataTriangleList(TDataTriangleList& triangleList)
|
|
{
|
|
|
|
BOOST_FOREACH(auto& i, triangleList.Vec2CoordArr)
|
|
{
|
|
i.second.clear();
|
|
}
|
|
|
|
BOOST_FOREACH(auto& i, triangleList.Vec3CoordArr)
|
|
{
|
|
i.second.clear();
|
|
}
|
|
|
|
return triangleList;
|
|
}
|
|
|
|
TDataTriangleList& InsertIntoDataTriangleList(TDataTriangleList& triangleList, const std::vector<vec3>& vertexArr, const std::vector<vec2>& texCoordArr)
|
|
{
|
|
triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].insert(triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].end(), vertexArr.begin(), vertexArr.end());
|
|
triangleList.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].insert(triangleList.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].end(), texCoordArr.begin(), texCoordArr.end());
|
|
|
|
return triangleList;
|
|
}
|
|
|
|
|
|
TTriangleList MakeTriangleList(vec2 posFrom, vec2 posTo, vec2 texCoordFrom, vec2 texCoordTo)
|
|
{
|
|
TTriangleList triangleList;
|
|
|
|
triangleList.Data = MakeDataTriangleList(posFrom, posTo, texCoordFrom, texCoordTo);
|
|
|
|
triangleList.RefreshBuffer();
|
|
|
|
return triangleList;
|
|
|
|
}
|
|
|
|
void Replace6PointsInTriangleList(TDataTriangleList& triangleList, int pos, vec2 posFrom, vec2 posTo, vec2 texCoordFrom, vec2 texCoordTo)
|
|
{
|
|
FillVertexCoordVec(triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB], pos, posFrom, posTo);
|
|
FillTexCoordVec(triangleList.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB], pos, texCoordFrom, texCoordTo);
|
|
}
|
|
|
|
void Replace6PointsInTriangleList_4Points(TDataTriangleList& triangleList, int pos, vec2 pos1, vec2 pos2, vec2 pos3, vec2 pos4, vec2 texCoord1, vec2 texCoord2, vec2 texCoord3, vec2 texCoord4)
|
|
{
|
|
FillVertexCoordVec_4Points(triangleList.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB], pos, pos1, pos2, pos3, pos4);
|
|
FillTexCoordVec_4Points(triangleList.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB], pos, texCoord1, texCoord2, texCoord3, texCoord4);
|
|
}
|
|
|
|
|
|
|
|
void CheckGlError(const std::string& msg)
|
|
{
|
|
AssertIfInMainThread();
|
|
|
|
cardinal error = glGetError();
|
|
|
|
if (error != GL_NO_ERROR)
|
|
{
|
|
if (msg == "")
|
|
{
|
|
throw ErrorToLog("Gl error = "+tostr(error));
|
|
}
|
|
else
|
|
{
|
|
throw ErrorToLog("Gl error = "+tostr(error) + "; with message = " + msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
} //namespace SE
|