-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgeometry.cpp
More file actions
163 lines (138 loc) · 5.75 KB
/
geometry.cpp
File metadata and controls
163 lines (138 loc) · 5.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include "geometry.h"
#include "main.h"
void Quaternion::set(double axis[3], double theta){
q[0] = cos(theta/2.0);
double sinthetadiv2 = sin(theta/2.0);
q[1] = axis[0]*sinthetadiv2;
q[2] = axis[1]*sinthetadiv2;
q[3] = axis[2]*sinthetadiv2;
}
glm::mat4x4 Quaternion::getMatrix(){// wikipedia based on
glm::mat4x4 retmat;
double s = 2.0/(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
double as = q[0] * s;double bs = q[1] * s;double cs = q[2] * s;double ds = q[3] * s;
double ab = q[0] * bs;double ac = q[0] * cs;double ad = q[0] * ds;
double bb = q[1] * bs;double bc = q[1] * cs;double bd = q[1] * ds;
double cc = q[2] * cs;double cd = q[2] * ds;double dd = q[3] * ds;
retmat[0][0] = 1-cc-dd;
retmat[0][1] = bc-ad;
retmat[0][2] = bd+ac;
retmat[1][0] = bc+ad;
retmat[1][1] = 1-bb-dd;
retmat[1][2] = cd-ab;
retmat[2][0] = bd-ac;
retmat[2][1] = cd+ab;
retmat[2][2] = 1-bb-cc;
retmat[0][3] = 0.0;
retmat[1][3] = 0.0;
retmat[2][3] = 0.0;
retmat[3][0] = 0.0;
retmat[3][1] = 0.0;
retmat[3][2] = 0.0;
retmat[3][3] = 1;// for translation matrix
return retmat;
}
Quaternion Quaternion::times(Quaternion quat){
Quaternion retq;
retq.q[0] = q[0]*quat.q[0] - q[1]*quat.q[1] - q[2]*quat.q[2] - q[3]*quat.q[3];// each of ii=jj=kk= -1 so real*real and -imag*imag
retq.q[1] = q[0]*quat.q[1] + q[1]*quat.q[0] + q[2]*quat.q[3] - q[3]*quat.q[2];// jk = i, kj = -i, 1*i = i, i*1 = i
retq.q[2] = q[0]*quat.q[2] - q[1]*quat.q[3] + q[2]*quat.q[0] + q[3]*quat.q[1];// ki = j, ik = -j, 1*j = j, j*1 = j
retq.q[3] = q[0]*quat.q[3] + q[1]*quat.q[2] - q[2]*quat.q[1] + q[3]*quat.q[0];// ij = k, ji = -k, 1*k = k, k*1 = k
return retq;
}
void Quaternion::renormalize(){
double s = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);// not sure this is most accurate way to renormalize
for (int i = 0; i < 4; i++){
q[i] = q[i]/s;
}
}
Model::Model(MemoryManager<Vertex>* vM, MemoryManager<uint16_t>* iM, std::vector<Vertex> verts, std::vector<uint16_t> inds){
vertsMM = vM;
indsMM = iM;
pos[0] = 0.0f;pos[1] = 0.0f;pos[2] = 0.0f;
double axis[3] = {0.0,0.0,1.0};
q.set(axis,0.0);
////glm::rotate(glm::mat4(1.0f),rotation[0],glm::vec3(rotation[1],rotation[2],rotation[3]))
modelTransform = q.getMatrix()*glm::translate(glm::mat4(1.0f),glm::vec3(pos[0],pos[1],pos[2]));
vertStart = vertsMM->alloc(verts.size());// request space
if (vertStart == -1){
throw std::runtime_error("no space in vertex buffer");
}
indsStart = indsMM->alloc(inds.size());// request space in other memory
if (indsStart == -1){
throw std::runtime_error("no space in index buffer");
}
vertLength = verts.size();
indsLength = inds.size();
vertsMem = vertsMM->getMemoryPointer(vertStart);// get pointers to memory allocated to us
indsMem = indsMM->getMemoryPointer(indsStart);
for (int i = 0; i < vertLength; i++){// fill in memory
vertsMem[i] = verts[i];
}
for (int i = 0; i < indsLength; i++){
indsMem[i] = inds[i];
}
vertsMM->updateBuffer();// update buffers need to make this more efficient later
indsMM->updateBuffer();
}
Model::~Model(){
vertsMM->free(vertStart);
indsMM->free(indsStart);
}
void Model::moveTo(float newPos[3]){
for (int i = 0; i < 3; i++){
pos[i] = newPos[i];
}
modelTransform = glm::translate(glm::mat4(1.0f),glm::vec3(pos[0],pos[1],pos[2]))*q.getMatrix();//glm::rotate(glm::mat4(1.0f),rotation[0],glm::vec3(rotation[1],rotation[2],rotation[3]));
}
void Model::setRotation(Quaternion quat){
for (int i = 0; i < 4; i++){
q.q[i] = quat.q[i];
}
modelTransform = glm::translate(glm::mat4(1.0f),glm::vec3(pos[0],pos[1],pos[2]))*q.getMatrix();//glm::rotate(glm::mat4(1.0f),rotation[0],glm::vec3(rotation[1],rotation[2],rotation[3]));
}
InstancedModel::InstancedModel(MemoryManager<Vertex>* v, MemoryManager<uint16_t>* i, std::vector<Vertex> verts, std::vector<uint16_t> inds)
: Model( v, i, verts, inds){// call parent constructor
}
InstancedModel::~InstancedModel() {// auto calls ~Model() after this finish
}
void InstancedModel::moveITo(int i, float newPos[3]){
if (transforms.size() < i+1){
while (i+1 > qs.size()){// need ith item to exist so size must be i+1 as 0 indexed
Quaternion newQ = Quaternion();
double axis[3] = {0,0,1};
newQ.set(axis,0);
qs.push_back(newQ);
}
while (i*3+3 > poses.size()){// need ith item to exist so size must be (i+1)*3 as 0 indexed
poses.push_back(0);
}
while (transforms.size() < i+1){// need ith item to exist so size must be i+1 as 0 indexed
transforms.push_back(glm::mat4x4());
}
}
for (int j = 0; j < 3; j++){
poses[3*i+j] = newPos[j];
}
transforms[i] = glm::translate(glm::mat4(1.0f),glm::vec3(poses[3*i],poses[3*i+1],poses[3*i+2]))*qs[i].getMatrix();
}
void InstancedModel::setIRotation(int i, Quaternion quat){
if (transforms.size() < i+1){
while (i+1 > qs.size()){// need ith item to exist so size must be i+1 as 0 indexed
Quaternion newQ = Quaternion();
double axis[3] = {0,0,1};
newQ.set(axis,0);
qs.push_back(newQ);
}
while (i*3+3 > poses.size()){// need ith item to exist so size must be (i+1)*3 as 0 indexed
poses.push_back(0);
}
while (transforms.size() < i+1){// need ith item to exist so size must be i+1 as 0 indexed
transforms.push_back(glm::mat4x4());
}
}
for (int j = 0; j < 4; j++){
qs[i].q[j] = quat.q[j];
}
transforms[i] = glm::translate(glm::mat4(1.0f),glm::vec3(poses[3*i],poses[3*i+1],poses[3*i+2]))*qs[i].getMatrix();
}