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