-
Notifications
You must be signed in to change notification settings - Fork 1
/
Sphere.h
147 lines (131 loc) · 4.11 KB
/
Sphere.h
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
#pragma once
#include "Shape.h"
#define _USE_MATH_DEFINES
#include <math.h>
class Sphere : public Shape
{
static const int RESOLUTION = 50;
public:
virtual ~Sphere() override
{
}
virtual Shape* clone() const override
{
return new Sphere(*this);
}
virtual void init(ParamSet& set) override
{
m_radius = set.getFloat("radius", 1.0f);
m_zmin = set.getFloat("zmin", m_radius);
m_zmax = set.getFloat("zmax", m_radius);
m_phimax = set.getFloat("phimax", 360.0f);
m_transform = ei::identity4x4();
// TODO scale radius?
}
virtual void applyTransform(const Matrix& mat) override
{
m_transform *= mat;
}
void applyTransformFront(const Matrix& mat) override
{
m_transform = mat * m_transform;
}
// method that was used to create sphere geometry. Leaving the code here for future reference
/*void makeGeometry(std::vector<bim::Chunk::FullVertex>& vert, std::vector<int>& indices, bim::Property::Val props) const override
{
vert.clear();
if(m_zmax != m_radius || m_zmin != m_radius)
System::warning("Sphere is created with open top or bottom.");
// Compute tessellation and step parameters
const float phiMax = float(m_phimax / 360.0f * 2.0f * M_PI);
float thetaMax = acosf(m_zmax / m_radius);
float thetaMin = acosf(-m_zmin / m_radius);
int resPhi = int(ceil(RESOLUTION * phiMax / 2.0f / M_PI));
int resTheta = int(ceil(RESOLUTION * abs(thetaMax - thetaMin) / M_PI));
float pStep = phiMax / (resPhi - 1);
float tStep = (thetaMax - thetaMin) / (resTheta - 1);
// Create vertices in rings
for(int t = 0; t < resTheta; ++t)
{
float theta = t * tStep + std::min(thetaMin, thetaMax);
float sinT = sin(theta);
float cosT = cos(theta);
for(int p = 0; p < resPhi; ++p)
{
float phi = p * pStep;
bim::Chunk::FullVertex vertex;
vertex.normal = Vector(sinT * sin(phi), sinT * cos(phi), cosT);
vertex.position = ei::transform(vertex.normal * m_radius, m_transform);
if(m_flipNormal) vertex.normal = - vertex.normal;
vertex.tangent = cross(Vector(0.0f, 1.0f, 0.0f), vertex.normal);
vertex.normal = transformDir(vertex.normal, m_transform);
vertex.tangent = transformDir(vertex.tangent, m_transform);
vertex.bitangent = cross(vertex.normal, vertex.tangent);
vertex.texCoord0 = ei::Vec2(p / float(resPhi - 1.0f), t / float(resTheta - 1));
vert.push_back(vertex);
}
}
// Create indices
for(int t = 0; t < resTheta-1; ++t)
{
int rowStart = t * resTheta;
int nextRowStart = (t+1) * resTheta;
for(int p = 0; p < resPhi-1; ++p)
{
//
// r+0 r+1
// *---*
// |\ |
// | \ |
// | \|
// *---*
// r+0 r+1
//
// Also, check if one of the triangles is degenerated (happens at caps).
// upper triangle
float area = len(cross(vert[rowStart + p + 1].position - vert[rowStart + p].position,
vert[nextRowStart + p + 1].position - vert[rowStart + p].position));
if(area > 0.0f)
{
indices.push_back(rowStart + p);
indices.push_back(rowStart + p + 1);
indices.push_back(nextRowStart + p + 1);
}
// lower triangle
area = len(cross(vert[nextRowStart + p + 1].position - vert[rowStart + p].position,
vert[nextRowStart + p].position - vert[rowStart + p].position));
if(area > 0.0f)
{
indices.push_back(rowStart + p);
indices.push_back(nextRowStart + p + 1);
indices.push_back(nextRowStart + p);
}
}
}
// assert indices range
for (const auto& i : indices)
{
assert(i >= 0 && i < vert.size());
}
}*/
virtual size_t estimateSize(size_t vertexSize) const override
{
const float phiMax = float(m_phimax / 360.0f * 2.0f * M_PI);
float thetaMax = acosf(m_zmax / m_radius);
float thetaMin = acosf(-m_zmin / m_radius);
int resPhi = int(ceil(RESOLUTION * phiMax / 2.0f / M_PI));
int resTheta = int(ceil(RESOLUTION * abs(thetaMax - thetaMin) / M_PI));
return resTheta * resPhi * vertexSize + (resTheta - 1) * (resPhi - 1) * 6 * sizeof(uint32);
}
void flipNormals() override
{
m_flipNormal = true;
}
private:
float m_radius = 1.0f;
float m_zmin = 1.0f;
float m_zmax = 1.0f;
float m_phimax = 360.0f;
Matrix m_transform;
bool m_flipNormal = false;
};