temp commit
[SARndbox.git] / LocalWaterTool.cpp
blob4fcce5c29d8d46f832b6d1ca3a3030b2d0438ade
1 /***********************************************************************
2 LocalWaterTool - Tool class to locally add or remove water from an
3 augmented reality sandbox.
4 Copyright (c) 2012-2013 Oliver Kreylos
6 This file is part of the Augmented Reality Sandbox (SARndbox).
8 The Augmented Reality Sandbox is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 The Augmented Reality Sandbox is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with the Augmented Reality Sandbox; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ***********************************************************************/
23 #include "LocalWaterTool.h"
25 #include <Misc/FunctionCalls.h>
26 #include <GL/gl.h>
27 #include <GL/Extensions/GLARBVertexProgram.h>
28 #include <GL/GLGeometryWrappers.h>
29 #include <GL/GLTransformationWrappers.h>
30 #include <Vrui/Vrui.h>
31 #include <Vrui/ToolManager.h>
32 #include <Vrui/DisplayState.h>
34 #include "WaterTable2.h"
35 #include "Sandbox.h"
37 /***************************************
38 Static elements of class LocalWaterTool:
39 ***************************************/
41 LocalWaterToolFactory* LocalWaterTool::factory = 0;
43 /*******************************
44 Methods of class LocalWaterTool:
45 *******************************/
47 LocalWaterToolFactory* LocalWaterTool::initClass(Vrui::ToolManager& toolManager) {
48 /* Create the tool factory: */
49 factory = new LocalWaterToolFactory("LocalWaterTool", "Manage Water Locally", 0, toolManager);
51 /* Set up the tool class' input layout: */
52 factory->setNumButtons(2);
53 factory->setButtonFunction(0, "Rain");
54 factory->setButtonFunction(1, "Dry");
56 /* Register and return the class: */
57 toolManager.addClass(factory, Vrui::ToolManager::defaultToolFactoryDestructor);
58 return factory;
61 LocalWaterTool::LocalWaterTool(const Vrui::ToolFactory* factory,
62 const Vrui::ToolInputAssignment& inputAssignment)
63 : Vrui::Tool(factory, inputAssignment),
64 addWaterFunction(0),
65 adding(0.0f) {
68 LocalWaterTool::~LocalWaterTool(void) {
71 void LocalWaterTool::initialize(void) {
72 /* Register a render function with the water table: */
73 if(application->waterTable != 0) {
74 addWaterFunction = Misc::createFunctionCall(this, &LocalWaterTool::addWater);
75 application->waterTable->addRenderFunction(addWaterFunction);
79 void LocalWaterTool::deinitialize(void) {
80 /* Unregister the render function from the water table: */
81 if(application->waterTable != 0)
82 application->waterTable->removeRenderFunction(addWaterFunction);
83 delete addWaterFunction;
84 addWaterFunction = 0;
87 const Vrui::ToolFactory* LocalWaterTool::getFactory(void) const {
88 return factory;
91 void LocalWaterTool::buttonCallback(int buttonSlotIndex,
92 Vrui::InputDevice::ButtonCallbackData* cbData) {
93 GLfloat waterAmount = application->rainStrength;
94 if(!cbData->newButtonState)
95 waterAmount = -waterAmount;
96 if(buttonSlotIndex == 1)
97 waterAmount = -waterAmount;
98 adding += waterAmount;
101 void LocalWaterTool::initContext(GLContextData& contextData) const {
102 /* Initialize the required OpenGL extensions: */
103 GLARBVertexProgram::initExtension();
106 void LocalWaterTool::glRenderActionTransparent(GLContextData& contextData) const {
107 glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
109 /* Go to navigational coordinates: */
110 glPushMatrix();
111 glLoadMatrix(Vrui::getDisplayState(contextData).modelviewNavigational);
113 /* Get the current rain disk position and size in camera coordinates: */
114 Vrui::Point rainPos = Vrui::getInverseNavigationTransformation().transform(getButtonDevicePosition(
115 0));
116 Vrui::Scalar rainRadius = Vrui::getPointPickDistance() * Vrui::Scalar(3);
118 /* Construct the rain cylinder: */
119 Vrui::Vector z = application->waterTable->getBaseTransform().inverseTransform(Vrui::Vector(0, 0,
120 1));
121 Vrui::Vector x = Geometry::normal(z);
122 Vrui::Vector y = Geometry::cross(z, x);
123 x.normalize();
124 y.normalize();
126 /* Set the rain cylinder's material: */
127 GLfloat diffuseCol[4] = {0.0f, 0.0f, 1.0f, 0.333f};
128 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuseCol);
130 /* Render the back faces of the rain cylinder: */
131 glCullFace(GL_FRONT);
132 glBegin(GL_QUAD_STRIP);
133 for(int i = 0; i <= 32; ++i) {
134 Vrui::Scalar angle = Vrui::Scalar(2) * Math::Constants<Vrui::Scalar>::pi * Vrui::Scalar(
135 i) / Vrui::Scalar(32);
136 glNormal(x * Math::cos(angle) + y * Math::sin(angle));
137 glVertex(rainPos + x * (Math::cos(angle)*rainRadius) + y * (Math::sin(angle)*rainRadius));
138 glVertex(rainPos + x * (Math::cos(angle)*rainRadius) + y * (Math::sin(
139 angle)*rainRadius) - z * Vrui::Scalar(50));
141 glEnd();
143 /* Render the front faces of the rain cylinder: */
144 glCullFace(GL_BACK);
145 glBegin(GL_QUAD_STRIP);
146 for(int i = 0; i <= 32; ++i) {
147 Vrui::Scalar angle = Vrui::Scalar(2) * Math::Constants<Vrui::Scalar>::pi * Vrui::Scalar(
148 i) / Vrui::Scalar(32);
149 glNormal(x * Math::cos(angle) + y * Math::sin(angle));
150 glVertex(rainPos + x * (Math::cos(angle)*rainRadius) + y * (Math::sin(angle)*rainRadius));
151 glVertex(rainPos + x * (Math::cos(angle)*rainRadius) + y * (Math::sin(
152 angle)*rainRadius) - z * Vrui::Scalar(50));
154 glEnd();
155 glBegin(GL_POLYGON);
156 glNormal(z);
157 for(int i = 0; i < 32; ++i) {
158 Vrui::Scalar angle = Vrui::Scalar(2) * Math::Constants<Vrui::Scalar>::pi * Vrui::Scalar(
159 i) / Vrui::Scalar(32);
160 glVertex(rainPos + x * (Math::cos(angle)*rainRadius) + y * (Math::sin(angle)*rainRadius));
162 glEnd();
164 glPopMatrix();
165 glPopAttrib();
168 void LocalWaterTool::addWater(GLContextData& contextData) const {
169 if(adding != 0.0f) {
170 glPushAttrib(GL_ENABLE_BIT);
171 glDisable(GL_CULL_FACE);
173 /* Get the current rain disk position and size in camera coordinates: */
174 Vrui::Point rainPos = Vrui::getInverseNavigationTransformation().transform(getButtonDevicePosition(
175 0));
176 Vrui::Scalar rainRadius = Vrui::getPointPickDistance() * Vrui::Scalar(3);
178 /* Render the rain disk: */
179 Vrui::Vector z = application->waterTable->getBaseTransform().inverseTransform(Vrui::Vector(0, 0,
180 1));
181 Vrui::Vector x = Geometry::normal(z);
182 Vrui::Vector y = Geometry::cross(z, x);
183 x *= rainRadius / Geometry::mag(x);
184 y *= rainRadius / Geometry::mag(y);
186 glVertexAttrib1fARB(1, adding / application->waterSpeed);
187 glBegin(GL_POLYGON);
188 for(int i = 0; i < 32; ++i) {
189 Vrui::Scalar angle = Vrui::Scalar(2) * Math::Constants<Vrui::Scalar>::pi * Vrui::Scalar(
190 i) / Vrui::Scalar(32);
191 glVertex(rainPos + x * Math::cos(angle) + y * Math::sin(angle));
193 glEnd();
195 glPopAttrib();