1 /* bzflag
2 * Copyright (c) 1993-2021 Tim Riker
3 *
4 * This package is free software; you can redistribute it and/or
5 * modify it under the terms of the license found in the file
6 * named COPYING that should have accompanied this file.
7 *
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12
13 // interface header
14 #include "FlagWarpSceneNode.h"
15
16 // system headers
17 #include <stdlib.h>
18 #include <math.h>
19
20 // common implementation headers
21 #include "StateDatabase.h"
22 #include "BZDBCache.h"
23
24 // local implementation headers
25 #include "ViewFrustum.h"
26
27 // FIXME (SceneRenderer.cxx is in src/bzflag)
28 #include "SceneRenderer.h"
29
30 const float FlagWarpSize = 7.5; // meters
31 const GLfloat FlagWarpAlpha = 0.5f;
32 const GLfloat FlagWarpSceneNode::color[7][3] =
33 {
34 { 0.25, 1.0, 0.25 },
35 { 0.25, 0.25, 1.0 },
36 { 1.0, 0.0, 1.0 },
37 { 1.0, 0.25, 0.25 },
38 { 1.0, 0.5, 0.0 },
39 { 1.0, 1.0, 0.0 },
40 { 1.0, 1.0, 1.0 }
41 };
42
FlagWarpSceneNode(const GLfloat pos[3])43 FlagWarpSceneNode::FlagWarpSceneNode(const GLfloat pos[3]) :
44 renderNode(this)
45 {
46 move(pos);
47 setRadius(1.25f * FlagWarpSize * FlagWarpSize);
48 size = 1.0f;
49 }
50
~FlagWarpSceneNode()51 FlagWarpSceneNode::~FlagWarpSceneNode()
52 {
53 // do nothing
54 }
55
setSizeFraction(GLfloat _size)56 void FlagWarpSceneNode::setSizeFraction(GLfloat _size)
57 {
58 size = _size;
59 }
60
move(const GLfloat pos[3])61 void FlagWarpSceneNode::move(const GLfloat pos[3])
62 {
63 setCenter(pos);
64 }
65
getDistance(const GLfloat * eye) const66 GLfloat FlagWarpSceneNode::getDistance(const GLfloat* eye) const
67 {
68 // shift position of warp down a little because a flag and it's warp
69 // are at the same position but we want the warp to appear below the
70 // flag.
71 const GLfloat* mySphere = getSphere();
72 return (eye[0] - mySphere[0]) * (eye[0] - mySphere[0]) +
73 (eye[1] - mySphere[1]) * (eye[1] - mySphere[1]) +
74 (eye[2] - mySphere[2] + 0.2f) * (eye[2] - mySphere[2] + 0.2f);
75 }
76
notifyStyleChange()77 void FlagWarpSceneNode::notifyStyleChange()
78 {
79 OpenGLGStateBuilder builder(gstate);
80 if (BZDBCache::blend)
81 {
82 builder.setBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
83 builder.setStipple(1.0f);
84 }
85 else
86 {
87 builder.resetBlending();
88 builder.setStipple(FlagWarpAlpha);
89 }
90 gstate = builder.getState();
91 }
92
addRenderNodes(SceneRenderer & renderer)93 void FlagWarpSceneNode::addRenderNodes(
94 SceneRenderer& renderer)
95 {
96 renderer.addRenderNode(&renderNode, &gstate);
97 }
98
99 //
100 // FlagWarpSceneNode::FlagWarpRenderNode
101 //
102
FlagWarpRenderNode(const FlagWarpSceneNode * _sceneNode)103 FlagWarpSceneNode::FlagWarpRenderNode::FlagWarpRenderNode(
104 const FlagWarpSceneNode* _sceneNode) :
105 sceneNode(_sceneNode)
106 {
107 // do nothing
108 }
109
~FlagWarpRenderNode()110 FlagWarpSceneNode::FlagWarpRenderNode::~FlagWarpRenderNode()
111 {
112 // do nothing
113 }
114
render()115 void FlagWarpSceneNode::FlagWarpRenderNode::render()
116 {
117 // make a perturbed ring
118 GLfloat geom[12][2];
119 for (int i = 0; i < 12; i++)
120 {
121 const GLfloat r = FlagWarpSize * (0.9f + 0.2f * (float)bzfrand());
122 geom[i][0] = r * cosf((float)(2.0 * M_PI * double(i) / 12.0));
123 geom[i][1] = r * sinf((float)(2.0 * M_PI * double(i) / 12.0));
124 }
125
126 const GLfloat* sphere = sceneNode->getSphere();
127 glPushMatrix();
128 glTranslatef(sphere[0], sphere[1], sphere[2]);
129
130 if (sphere[2] > RENDERER.getViewFrustum().getEye()[2])
131 {
132 for (int i = 0; i < 7; i++)
133 {
134 GLfloat s = sceneNode->size - 0.05f * float(i);
135 if (s < 0.0f) break;
136 myColor4f(color[i][0], color[i][1], color[i][2], FlagWarpAlpha);
137 glBegin(GL_TRIANGLE_FAN);
138 glVertex2f(0.0f, 0.0f);
139 glVertex2f(s * geom[0][0], s * geom[0][1]);
140 glVertex2f(s * geom[11][0], s * geom[11][1]);
141 glVertex2f(s * geom[10][0], s * geom[10][1]);
142 glVertex2f(s * geom[9][0], s * geom[9][1]);
143 glVertex2f(s * geom[8][0], s * geom[8][1]);
144 glVertex2f(s * geom[7][0], s * geom[7][1]);
145 glVertex2f(s * geom[6][0], s * geom[6][1]);
146 glVertex2f(s * geom[5][0], s * geom[5][1]);
147 glVertex2f(s * geom[4][0], s * geom[4][1]);
148 glVertex2f(s * geom[3][0], s * geom[3][1]);
149 glVertex2f(s * geom[2][0], s * geom[2][1]);
150 glVertex2f(s * geom[1][0], s * geom[1][1]);
151 glVertex2f(s * geom[0][0], s * geom[0][1]);
152 glEnd(); // 14 verts -> 12 tris
153 addTriangleCount(12);
154 glTranslatef(0.0f, 0.0f, -0.01f);
155 }
156 }
157 else
158 {
159 for (int i = 0; i < 7; i++)
160 {
161 GLfloat s = sceneNode->size - 0.05f * float(i);
162 if (s < 0.0f) break;
163 myColor4f(color[i][0], color[i][1], color[i][2], FlagWarpAlpha);
164 glBegin(GL_TRIANGLE_FAN);
165 glVertex2f(0.0f, 0.0f);
166 glVertex2f(s * geom[0][0], s * geom[0][1]);
167 glVertex2f(s * geom[1][0], s * geom[1][1]);
168 glVertex2f(s * geom[2][0], s * geom[2][1]);
169 glVertex2f(s * geom[3][0], s * geom[3][1]);
170 glVertex2f(s * geom[4][0], s * geom[4][1]);
171 glVertex2f(s * geom[5][0], s * geom[5][1]);
172 glVertex2f(s * geom[6][0], s * geom[6][1]);
173 glVertex2f(s * geom[7][0], s * geom[7][1]);
174 glVertex2f(s * geom[8][0], s * geom[8][1]);
175 glVertex2f(s * geom[9][0], s * geom[9][1]);
176 glVertex2f(s * geom[10][0], s * geom[10][1]);
177 glVertex2f(s * geom[11][0], s * geom[11][1]);
178 glVertex2f(s * geom[0][0], s * geom[0][1]);
179 glEnd(); // 14 verts -> 12 tris
180 addTriangleCount(12);
181 glTranslatef(0.0f, 0.0f, 0.01f);
182 }
183 }
184
185 glPopMatrix();
186 }
187
188 // Local Variables: ***
189 // mode: C++ ***
190 // tab-width: 4 ***
191 // c-basic-offset: 4 ***
192 // indent-tabs-mode: nil ***
193 // End: ***
194 // ex: shiftwidth=4 tabstop=4
195