1 /* switch.cc
2 A switch which can be triggered by user to accomplish something
3
4 Copyright (C) 2000 Mathias Broxvall
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "switch.h"
22
23 #include "game.h"
24 #include "guile.h"
25 #include "map.h"
26 #include "player.h"
27 #include "sound.h"
28
CSwitch(Game & g,Real x,Real y,SCM on,SCM off)29 CSwitch::CSwitch(Game &g, Real x, Real y, SCM on, SCM off)
30 : Animated(g, Role_OtherAnimated, 1) {
31 position[0] = x;
32 position[1] = y;
33 position[2] = game.map->getHeight(x, y);
34 primaryColor = Color(0.8, 0.8, 0.8, 1.0);
35 secondaryColor = Color(0., 0., 0., 1.);
36 is_touched = false;
37 this->on = on;
38 this->off = off;
39 if (on) scm_gc_protect_object(on);
40 if (off) scm_gc_protect_object(off);
41 }
~CSwitch()42 CSwitch::~CSwitch() { CSwitch::releaseCallbacks(); }
releaseCallbacks()43 void CSwitch::releaseCallbacks() {
44 if (on) scm_gc_unprotect_object(on);
45 if (off) scm_gc_unprotect_object(off);
46 on = NULL;
47 off = NULL;
48 }
49
generateBuffers(const GLuint * idxbufs,const GLuint * databufs,const GLuint * vaolist,bool mustUpdate) const50 void CSwitch::generateBuffers(const GLuint *idxbufs, const GLuint *databufs,
51 const GLuint *vaolist, bool mustUpdate) const {
52 const int nfacets = 16;
53 GLfloat lever_length = 0.3f;
54 GLfloat lever_end = 0.03f;
55 GLfloat body_wid = 0.15f;
56 GLfloat body_rad = 0.15f;
57
58 GLfloat data[4 * nfacets + 7][8];
59 ushort idxs[4 * nfacets + 6][3];
60
61 Color side_color = is_on ? primaryColor : secondaryColor;
62
63 GLfloat flat[3] = {0.f, 0.f, 0.f};
64 char *pos = (char *)data;
65 // Top curve
66 for (int i = 0; i < nfacets; i++) {
67 GLfloat angle = i * M_PI / (nfacets - 1);
68 GLfloat norm[3] = {std::cos(angle), 0., std::sin(angle)};
69 pos +=
70 packObjectVertex(pos, position[0] + body_wid, position[1] + body_rad * std::cos(angle),
71 position[2] + body_rad * std::sin(angle), 0., 0., primaryColor, norm);
72 pos +=
73 packObjectVertex(pos, position[0] - body_wid, position[1] + body_rad * std::cos(angle),
74 position[2] + body_rad * std::sin(angle), 0., 0., primaryColor, norm);
75 }
76 // Side panels
77 for (int i = 0; i < nfacets; i++) {
78 GLfloat angle = i * M_PI / (nfacets - 1);
79 pos +=
80 packObjectVertex(pos, position[0] + body_wid, position[1] + body_rad * std::cos(angle),
81 position[2] + body_rad * std::sin(angle), 0., 0., side_color, flat);
82 }
83 for (int i = 0; i < nfacets; i++) {
84 GLfloat angle = i * M_PI / (nfacets - 1);
85 pos +=
86 packObjectVertex(pos, position[0] - body_wid, position[1] + body_rad * std::cos(angle),
87 position[2] + body_rad * std::sin(angle), 0., 0., side_color, flat);
88 }
89 pos += packObjectVertex(pos, position[0] + body_wid, position[1], position[2], 0., 0.,
90 side_color, flat);
91 pos += packObjectVertex(pos, position[0] - body_wid, position[1], position[2], 0., 0.,
92 side_color, flat);
93
94 for (int i = 0; i < nfacets; i++) {
95 int j = (i + 1) % nfacets;
96 idxs[2 * i][0] = 2 * i;
97 idxs[2 * i][1] = 2 * i + 1;
98 idxs[2 * i][2] = 2 * j + 1;
99 idxs[2 * i + 1][0] = 2 * j;
100 idxs[2 * i + 1][1] = 2 * i;
101 idxs[2 * i + 1][2] = 2 * j + 1;
102 }
103
104 for (int i = 0; i < nfacets; i++) {
105 idxs[2 * nfacets + i][0] = 2 * nfacets + i;
106 idxs[2 * nfacets + i][1] = 2 * nfacets + (i + 1) % nfacets;
107 idxs[2 * nfacets + i][2] = 4 * nfacets;
108 }
109
110 for (int i = 0; i < nfacets; i++) {
111 idxs[3 * nfacets + i][0] = 3 * nfacets + (i + 1) % nfacets;
112 idxs[3 * nfacets + i][1] = 3 * nfacets + i;
113 idxs[3 * nfacets + i][2] = 4 * nfacets + 1;
114 }
115
116 // Draw Lever
117 int sgn = is_on ? 1 : -1;
118 pos +=
119 packObjectVertex(pos, position[0], position[1], position[2], 0., 0., primaryColor, flat);
120 pos += packObjectVertex(
121 pos, position[0] + lever_end * 1.4f, position[1] + sgn * (lever_length - lever_end),
122 position[2] + (lever_length + lever_end), 0., 0., primaryColor, flat);
123 pos += packObjectVertex(
124 pos, position[0] - lever_end * 1.4f, position[1] + sgn * (lever_length - lever_end),
125 position[2] + (lever_length + lever_end), 0., 0., primaryColor, flat);
126 pos += packObjectVertex(
127 pos, position[0] - lever_end * 1.4f, position[1] + sgn * (lever_length + lever_end),
128 position[2] + (lever_length - lever_end), 0., 0., primaryColor, flat);
129 pos += packObjectVertex(
130 pos, position[0] + lever_end * 1.4f, position[1] + sgn * (lever_length + lever_end),
131 position[2] + (lever_length - lever_end), 0., 0., primaryColor, flat);
132 int vstart = 4 * nfacets + 2;
133 int istart = 4 * nfacets;
134 ushort local[6][3] = {{0, 1, 2}, {0, 2, 3}, {0, 3, 4}, {0, 4, 1}, {1, 3, 2}, {1, 4, 3}};
135 for (int i = 0; i < 6; i++) {
136 idxs[istart + i][0] = local[i][0] + vstart;
137 idxs[istart + i][1] = local[i][1] + vstart;
138 idxs[istart + i][2] = local[i][2] + vstart;
139 }
140
141 glBindVertexArray(vaolist[0]);
142 glBindBuffer(GL_ARRAY_BUFFER, databufs[0]);
143 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
144 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idxbufs[0]);
145 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idxs), idxs, GL_STATIC_DRAW);
146 configureObjectAttributes();
147 }
148
drawBuffers1(const GLuint * vaolist) const149 void CSwitch::drawBuffers1(const GLuint *vaolist) const {
150 glDisable(GL_BLEND);
151 glEnable(GL_CULL_FACE);
152
153 const int nfacets = 16;
154 setActiveProgramAndUniforms(Shader_Object);
155 setObjectUniforms(specularColor, 0.12, Lighting_Regular);
156 glBindTexture(GL_TEXTURE_2D, textureBlank);
157
158 glBindVertexArray(vaolist[0]);
159 glDrawElements(GL_TRIANGLES, (4 * nfacets + 6) * 3, GL_UNSIGNED_SHORT, (void *)0);
160 }
161
drawBuffers2(const GLuint *) const162 void CSwitch::drawBuffers2(const GLuint * /*vaolist*/) const {}
163
tick(Real t)164 void CSwitch::tick(Real t) {
165 Animated::tick(t);
166
167 Coord3d v = position - game.player1->position;
168 Player *player = game.player1;
169
170 double dist = length(v);
171 if (dist < player->radius + 0.3) {
172 if (!is_touched) {
173 if (is_on) {
174 is_on = false;
175 game.queueCall(off);
176 drawChanged = true;
177 } else {
178 is_on = true;
179 game.queueCall(on);
180 drawChanged = true;
181 }
182 playEffect(SFX_SWITCH);
183 }
184 is_touched = true;
185 } else
186 is_touched = false;
187 }
188