/
pyramid.nt
186 lines (179 loc) · 5.9 KB
/
pyramid.nt
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
module pyramid;
import std.lib.sdl_base, std.lib.opengl.(, window, camera, sdl), gd, std.file;
import c.GL.glext;
platform(i686-mingw32) {
pragma(lib, "winmm");
pragma(lib, "gdi32");
pragma(lib, "png");
pragma(lib, "z");
}
import std.time;
import std.macros.switchover;
void main(string[] args) {
auto img = gdImageCreateFromPngPtr(readAll "8r.png" #.(length, ptr));
// resizeWindow (640, 480);
auto vertices = [vec3f (-1, -1, -1), vec3f(1, 1, 1)];
void dividePyramid(
type-of &vertices pCorners,
void delegate(type-of &vertices) callback) {
auto a = (*pCorners)[0], b = (*pCorners)[1];
for auto v <- [for tup <- cross (0..3, 0..3, 0..3): vec3i(tup)] {
int bsum = (v.x == 1) + (v.y == 1) + (v.z == 1);
if bsum < 2 {
vec3f x 2 temp = [a * (3 - v) / 3f + b * (v + 0) / 3f,
a * (2 - v) / 3f + b * (v + 1) / 3f];
callback &temp;
}
}
}
auto ec = new EgoCam!PerspectiveCam (vec3f(0, 0, -3), 0, 0);
bool pass;
vec3f[auto~] vertexQuadData, colorQuadData;
int[auto~] vertexIndexData;
void addVertex(vec3f pos, vec3f col) {
auto limit = vertexQuadData.length - 64;
if (limit < 0) limit = 0;
alias eps = 0.00001f;
for (int i = vertexQuadData.length - 1; i >= limit; --i) {
if (|vertexQuadData[i] - pos| < eps) { vertexIndexData ~= i; return; }
}
vertexIndexData ~= vertexQuadData.length;
vertexQuadData ~= pos;
colorQuadData ~= col;
}
void rootFun(type-of &vertices pVecs) {
alias twoVecs = *pVecs;
auto vecs = [for
tup <- cross(0..2, 0..2, 0..2):
vec3f(twoVecs[tup[0]].x, twoVecs[tup[1]].y, twoVecs[tup[2]].z)];
for (int i, int id) <- zip (ints,
[0, 1, 3, 2,
2, 3, 7, 6,
6, 7, 5, 4,
4, 5, 1, 0,
1, 5, 7, 3,
2, 6, 4, 0])
{
auto vec = vecs[id];
addVertex (vec, vec + vec3f(1, 0.6, 0.3) * (i / 24f));
}
}
auto mkFun(int depth) {
auto curFun = &rootFun;
for 0..depth
curFun = new \(type-of &vertices pVecs) { dividePyramid(pVecs, curFun); };
return curFun;
}
int curDepth = 1;
GLuint x 3 lists;
void regenList() using mode GL {
if (lists[0]) DeleteBuffers(3, lists.ptr);
GenBuffers(3, lists.ptr);
vertexQuadData.free; colorQuadData.free;
vertexIndexData.free;
writeln "call with $curDepth";
auto fun = mkFun curDepth;
writeln "compute";
fun &vertices;
writeln "upload $(vertexQuadData.length) vertices, $(vertexIndexData.length) indices. ";
for (int i, vec3f[] list) <- zip(0..2, [vertexQuadData[], colorQuadData[]]) using GL_ARRAY_BUFFER_ARB {
BindBuffer lists[i];
BufferData ((size-of vec3f) * list.length, list.ptr, STATIC_DRAW);
}
using ELEMENT_ARRAY_BUFFER {
BindBuffer lists[2];
// BufferData (4 * vertexIndexData.length, vertexIndexData.ptr, STATIC_DRAW);
BufferData vertexIndexData.(4 * length, ptr, STATIC_DRAW);
}
}
bool active;
void toggleActive() using prefix SDL_ {
if (active) {
ShowCursor true;
} else {
ShowCursor false;
// WM_GrabInput(GRAB_ON);
WarpMouse(320, 240);
}
active = !active;
}
glwindow = new SDLWindow;
glwindow.context-callbacks ~= \{
writeln "regenList()";
regenList();
};
{
int res;
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &res);
writeln "0 or 1, enable or disable double buffering: $(res)";
using prefix SDL_GL_ using suffix _SIZE for (int num, string info) <- [
(RED, "framebuffer red component"),
(GREEN, "framebuffer green component"),
(BLUE, "framebuffer blue component"),
(ALPHA, "framebuffer alpha component"),
(BUFFER, "framebuffer"),
(DEPTH, "depth buffer"),
(STENCIL, "stencil buffer"),
(ACCUM_RED, "accumulation buffer red component"),
(ACCUM_GREEN, "accumulation buffer green component"),
(ACCUM_BLUE, "accumulation buffer blue component"),
(ACCUM_ALPHA, "accumulation buffer alpha component")]
{
SDL_GL_GetAttribute(num, &res);
writeln "Size of the $info, in bits: $res";
}
}
vec2i lastmousepos;
int frame;
auto lastsec = sec();
while true {
using mode GL {
ClearColor (0 x 3, 0);
ClearDepth 1;
Clear (COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT);
ec.aspect = glwindow.size().(x * 1f / y);
ec.apply();
// Rotatef (t++, 0, 1, 0);
EnableClientState VERTEX_ARRAY;
EnableClientState COLOR_ARRAY;
ARRAY_BUFFER.BindBuffer lists[0];
VertexPointer(3, GL_FLOAT, size-of vec3f, null);
ARRAY_BUFFER.BindBuffer lists[1];
ColorPointer(3, GL_FLOAT, size-of vec3f, null);
ELEMENT_ARRAY_BUFFER.BindBuffer lists[2];
// DrawArrays (QUADS, 0, vertexQuadData.length);
DrawElements (QUADS, vertexIndexData.length, UNSIGNED_INT, null);
}
glwindow.update;
if (active) {
alias mouse-pos = glwindow.mouse-pos;
auto idelta = mouse-pos - lastmousepos;
lastmousepos = mouse-pos;
auto delta = vec2f((0.001 * idelta).(x, y));
using (ec, delta) { turn-left-x; turn-up-y; } // *MWAHAHAHAHAAAAAHAHA*
bool mustwarp;
alias border = 50;
if (mouse-pos.x < border || mouse-pos.y < border
|| mouse-pos.x > glwindow.size().x - border || mouse-pos.y > glwindow.size().y - border)
mustwarp = true;
if mustwarp {
lastmousepos = vec2i(320, 240);
SDL_WarpMouse lastmousepos;
}
}
if (mouse-clicked) toggleActive;
alias movestep = 0.034;
using prefix SDLK_ {
switch int i over keyPressed[i] {
case w: ec.pos += ec.dir * movestep;
case s: ec.pos -= ec.dir * movestep;
case a: ec.pos += ec.left * movestep;
case d: ec.pos -= ec.left * movestep;
}
switch int i over keyPushed[i] {
case PLUS or KP_PLUS: curDepth ++; regenList;
case MINUS or KP_MINUS: if curDepth curDepth --; regenList;
}
}
}
}