1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4     (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 Also see acknowledgements in Readme.html
9 
10 You may use this sample code for anything you like, it is not covered by the
11 same license as the rest of the engine.
12 -----------------------------------------------------------------------------
13 */
14 
15 #ifndef _Sample_Ocean_H_
16 #define _Sample_Ocean_H_
17 
18 #include "SdkSample.h"
19 #include "SamplePlugin.h"
20 #include "MaterialControls.h"
21 
22 using namespace Ogre;
23 using namespace OgreBites;
24 
25 #define MINSPEED .150f
26 #define MOVESPEED 30
27 #define MAXSPEED 1.800f
28 
29 #define CONTROLS_PER_PAGE 5
30 
31 enum OceanMaterial {
32 	OCEAN1_CG,
33 	OCEAN1_NATIVE,
34 	OCEAN2_CG,
35 	OCEAN2_NATIVE
36 };
37 
38 class _OgreSampleClassExport Sample_Ocean : public SdkSample
39 {
40 public:
41 	Sample_Ocean();
42 protected:
43 	//Things from the frame listener
44 	Ogre::Vector3 mTranslateVector;
45     int mSceneDetailIndex;
46     float mUpdateFreq;
47 	bool mSpinLight;
48     // just to stop toggles flipping too fast
49     Ogre::TextureFilterOptions mFiltering;
50     int mAniso;
51 
52 	Ogre::SceneNode*	  mMainNode;
53 	Ogre::Entity*         mOceanSurfaceEnt;
54 
55 	size_t				  mCurrentMaterial;
56 	size_t				  mCurrentPage;
57 	size_t				  mNumPages;
58 	Ogre::MaterialPtr	  mActiveMaterial;
59 	Ogre::Pass*			  mActivePass;
60 	Ogre::GpuProgramPtr	  mActiveFragmentProgram;
61 	Ogre::GpuProgramPtr	  mActiveVertexProgram;
62 	Ogre::GpuProgramParametersSharedPtr mActiveFragmentParameters;
63 	Ogre::GpuProgramParametersSharedPtr mActiveVertexParameters;
64 	Real				  mRotateSpeed;
65 	Slider* mShaderControls[CONTROLS_PER_PAGE];
66 
67 	ShaderControlsContainer    mShaderControlContainer;
68     MaterialControlsContainer mMaterialControlsContainer;
69 
70 	void setupGUI();
71 	void setupScene();
72 	virtual void setupContent();
73 	virtual void cleanupContent();
74 
75 	void sliderMoved(Slider* slider);
76 	void buttonHit(OgreBites::Button* button);
77 	void checkBoxToggled(CheckBox* box);
78 	void selectOceanMaterial(OceanMaterial newMaterial);
79 	void itemSelected(SelectMenu* menu);
80 	void changePage(int nextPage = -1);
81 	virtual bool frameRenderingQueued(const FrameEvent& evt);
82 };
83 
84 /**********************************************************************
85   Static declarations
86 **********************************************************************/
87 // Lights
88 #define NUM_LIGHTS 1
89 
90 // the light
91 Ogre::Light* mLights[NUM_LIGHTS];
92 // billboards for lights
93 Ogre::BillboardSet* mLightFlareSets[NUM_LIGHTS];
94 Ogre::Billboard* mLightFlares[NUM_LIGHTS];
95 // Positions for lights
96 Ogre::Vector3 mLightPositions[NUM_LIGHTS] =
97 {
98 	Ogre::Vector3(00, 400, 00)
99 };
100 // Base orientations of the lights
101 Ogre::Real mLightRotationAngles[NUM_LIGHTS] = { 35 };
102 Ogre::Vector3 mLightRotationAxes[NUM_LIGHTS] = {
103     Ogre::Vector3::UNIT_X
104 };
105 // Rotation speed for lights, degrees per second
106 Ogre::Real mLightSpeeds[NUM_LIGHTS] = { 30};
107 
108 // Colours for the lights
109 Ogre::ColourValue mDiffuseLightColours[NUM_LIGHTS] =
110 {
111 	Ogre::ColourValue(0.6, 0.6, 0.6)
112 };
113 
114 Ogre::ColourValue mSpecularLightColours[NUM_LIGHTS] =
115 {
116 	Ogre::ColourValue(0.5, 0.5, 0.5)
117 };
118 
119 // Which lights are enabled
120 bool mLightState[NUM_LIGHTS] =
121 {
122 	true
123 };
124 
125 // the light nodes
126 Ogre::SceneNode* mLightNodes[NUM_LIGHTS];
127 // the light node pivots
128 Ogre::SceneNode* mLightPivots[NUM_LIGHTS];
129 
130 
Sample_Ocean()131 Sample_Ocean::Sample_Ocean()
132 {
133 	mInfo["Title"] = "Ocean";
134 	mInfo["Description"] = "An example demonstrating ocean rendering using shaders.";
135 	mInfo["Thumbnail"] = "thumb_ocean.png";
136 	mInfo["Category"] = "Environment";
137 }
138 /*************************************************************************
139 	                    Sample_Ocean Methods
140 *************************************************************************/
cleanupContent()141 void Sample_Ocean::cleanupContent()
142 {
143     MeshManager::getSingleton().remove("OceanSurface");
144 
145 	// get rid of the shared pointers before shutting down ogre or exceptions occur
146     mActiveFragmentProgram.setNull();
147     mActiveFragmentParameters.setNull();
148     mActiveVertexProgram.setNull();
149     mActiveVertexParameters.setNull();
150     mActiveMaterial.setNull();
151 }
152 
153 //--------------------------------------------------------------------------
setupGUI(void)154 void Sample_Ocean::setupGUI(void)
155 {
156 	SelectMenu* selectMenu = mTrayMgr->createLongSelectMenu(
157 		TL_TOPLEFT, "MaterialSelectMenu", "Material", 300, 200, 5);
158 
159 	for (size_t i=0; i<mMaterialControlsContainer.size(); i++)
160 	{
161 		selectMenu->addItem(mMaterialControlsContainer[i].getDisplayName());
162 	}
163 
164 	mTrayMgr->createCheckBox(TL_TOPLEFT, "SpinLightButton", "Spin Light", 175)->setChecked(true);
165 
166 	mTrayMgr->createButton(TL_TOPRIGHT, "PageButtonControl", "Page", 175);
167 
168 	for (size_t i=0; i<CONTROLS_PER_PAGE; i++)
169 	{
170 		mShaderControls[i] = mTrayMgr->createThickSlider(TL_TOPRIGHT,
171 			"ShaderControlSlider" + StringConverter::toString(i), "Control", 256, 80, 0, 1, 100);
172 	}
173 
174 	selectMenu->selectItem(0);
175 	mTrayMgr->showCursor();
176 
177 }
178 //--------------------------------------------------------------------------
setupContent(void)179 void Sample_Ocean::setupContent(void)
180 {
181 	loadAllMaterialControlFiles(mMaterialControlsContainer);
182 	setupScene();
183 	setupGUI();
184 
185 	// Position it at 500 in Z direction
186     mCamera->setPosition(Ogre::Vector3(0,0,0));
187     // Look back along -Z
188     mCamera->lookAt(Ogre::Vector3(0,0,-300));
189     mCamera->setNearClipDistance(1);
190 
191 #if OGRE_PLATFORM != OGRE_PLATFORM_APPLE_IOS
192     setDragLook(true);
193 #endif
194 }
195 
setupScene()196 void Sample_Ocean::setupScene()
197 {
198 	// Set ambient light
199     mSceneMgr->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3));
200 	mSceneMgr->setSkyBox(true, "SkyBox", 1000);
201 
202     mMainNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
203 
204 
205     for (unsigned int i = 0; i < NUM_LIGHTS; ++i)
206     {
207         mLightPivots[i] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
208         mLightPivots[i]->rotate(mLightRotationAxes[i], Ogre::Angle(mLightRotationAngles[i]));
209         // Create a light, use default parameters
210         mLights[i] = mSceneMgr->createLight("Light" + Ogre::StringConverter::toString(i));
211 		mLights[i]->setPosition(mLightPositions[i]);
212 		mLights[i]->setDiffuseColour(mDiffuseLightColours[i]);
213 		mLights[i]->setSpecularColour(mSpecularLightColours[i]);
214 		mLights[i]->setVisible(mLightState[i]);
215 		//mLights[i]->setAttenuation(400, 0.1 , 1 , 0);
216         // Attach light
217         mLightPivots[i]->attachObject(mLights[i]);
218 		// Create billboard for light
219         mLightFlareSets[i] = mSceneMgr->createBillboardSet("Flare" + Ogre::StringConverter::toString(i));
220 		mLightFlareSets[i]->setMaterialName("LightFlare");
221 		mLightPivots[i]->attachObject(mLightFlareSets[i]);
222 		mLightFlares[i] = mLightFlareSets[i]->createBillboard(mLightPositions[i]);
223 		mLightFlares[i]->setColour(mDiffuseLightColours[i]);
224 		mLightFlareSets[i]->setVisible(mLightState[i]);
225     }
226 
227     // move the camera a bit right and make it look at the knot
228 	mCamera->moveRelative(Ogre::Vector3(50, 0, 100));
229 	mCamera->lookAt(0, 0, 0);
230 
231     // Define a plane mesh that will be used for the ocean surface
232     Ogre::Plane oceanSurface;
233     oceanSurface.normal = Ogre::Vector3::UNIT_Y;
234     oceanSurface.d = 20;
235     Ogre::MeshManager::getSingleton().createPlane("OceanSurface",
236         Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
237         oceanSurface,
238         1000, 1000, 50, 50, true, 1, 1, 1, Ogre::Vector3::UNIT_Z);
239 
240     mOceanSurfaceEnt = mSceneMgr->createEntity( "OceanSurface", "OceanSurface" );
241     mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mOceanSurfaceEnt);
242 }
243 
244 
245 //--------------------------------------------------------------------------
sliderMoved(Slider * slider)246 void Sample_Ocean::sliderMoved(Slider* slider)
247 {
248 	using namespace Ogre;
249 
250 	int sliderIndex = -1;
251 	for (int i=0; i<CONTROLS_PER_PAGE; i++)
252 	{
253 		if (mShaderControls[i] == slider)
254 		{
255 			sliderIndex = i;
256 			break;
257 		}
258 	}
259 	assert(sliderIndex != -1);
260 
261 	size_t index = mCurrentPage * CONTROLS_PER_PAGE + sliderIndex;
262     const ShaderControl& ActiveShaderDef = mMaterialControlsContainer[mCurrentMaterial].getShaderControl(index);
263 
264 	float val = slider->getValue();
265 
266 	if(mActivePass)
267 	{
268 		switch(ActiveShaderDef.ValType)
269 		{
270 			case GPU_VERTEX:
271 			case GPU_FRAGMENT:
272 				{
273 					GpuProgramParametersSharedPtr activeParameters =
274 						(ActiveShaderDef.ValType == GPU_VERTEX) ?
275 							mActiveVertexParameters : mActiveFragmentParameters;
276 
277 					if(!activeParameters.isNull())
278 					{
279 						activeParameters->_writeRawConstant(
280 							ActiveShaderDef.PhysicalIndex + ActiveShaderDef.ElementIndex, val);
281 					}
282 				}
283 				break;
284 
285 			case MAT_SPECULAR:
286 				{
287 					// get the specular values from the material pass
288 					ColourValue OldSpec(mActivePass->getSpecular());
289 					OldSpec[ActiveShaderDef.ElementIndex] = val;
290 					mActivePass->setSpecular( OldSpec );
291 				}
292 
293 				break;
294 
295 			case MAT_DIFFUSE:
296 				{
297 					// get the specular values from the material pass
298 					ColourValue OldSpec(mActivePass->getDiffuse());
299 					OldSpec[ActiveShaderDef.ElementIndex] = val;
300 					mActivePass->setDiffuse( OldSpec );
301 				}
302 				break;
303 
304 			case MAT_AMBIENT:
305 				{
306 					// get the specular values from the material pass
307 					ColourValue OldSpec(mActivePass->getAmbient());
308 					OldSpec[ActiveShaderDef.ElementIndex] = val;
309 					mActivePass->setAmbient( OldSpec );
310 				}
311 				break;
312 
313 			case MAT_SHININESS:
314 				// get the specular values from the material pass
315 				mActivePass->setShininess( val );
316 				break;
317 
318             case MAT_EMISSIVE:
319                 break;
320 		}
321 	}
322 }
323 
324 //--------------------------------------------------------------------------
changePage(int pageNum)325 void Sample_Ocean::changePage(int pageNum /* = -1 : toggle */)
326 {
327 	if (mMaterialControlsContainer.empty()) return;
328 	mCurrentPage = (pageNum == -1) ? (mCurrentPage+1) % mNumPages : pageNum;
329 
330 	static char pageText[64];
331 	sprintf(pageText, "Parameters %lu / %d", mCurrentPage+1, (int)mNumPages);
332 	static_cast<OgreBites::Button*>(mTrayMgr->getWidget("PageButtonControl"))->setCaption(pageText);
333 
334     if(!mActiveMaterial.isNull() && mActiveMaterial->getNumSupportedTechniques())
335 	{
336         Ogre::Technique* currentTechnique = mActiveMaterial->getSupportedTechnique(0);
337 		if(currentTechnique)
338 		{
339 			mActivePass = currentTechnique->getPass(0);
340 			if(mActivePass)
341 			{
342                 if (mActivePass->hasFragmentProgram())
343                 {
344 				    mActiveFragmentProgram = mActivePass->getFragmentProgram();
345     				mActiveFragmentParameters = mActivePass->getFragmentProgramParameters();
346                 }
347                 if (mActivePass->hasVertexProgram())
348                 {
349 				    mActiveVertexProgram = mActivePass->getVertexProgram();
350 				    mActiveVertexParameters = mActivePass->getVertexProgramParameters();
351                 }
352 
353                 size_t activeControlCount = mMaterialControlsContainer[mCurrentMaterial].getShaderControlCount();
354 
355 				size_t startControlIndex = mCurrentPage * CONTROLS_PER_PAGE;
356 				int numControls = static_cast<int>(activeControlCount - startControlIndex);
357 				if (numControls <= 0)
358 				{
359 					mCurrentPage = 0;
360 					startControlIndex = 0;
361 					numControls = (int)activeControlCount;
362 				}
363 
364 				for (size_t i=0; i<CONTROLS_PER_PAGE; i++)
365 				{
366 					Slider* shaderControlSlider = mShaderControls[i];
367 					if (i < (size_t)numControls)
368 					{
369 						shaderControlSlider->show();
370 						size_t controlIndex = startControlIndex + i;
371 						const ShaderControl& ActiveShaderDef = mMaterialControlsContainer[mCurrentMaterial].getShaderControl(controlIndex);
372 						shaderControlSlider->setRange(ActiveShaderDef.MinVal, ActiveShaderDef.MaxVal, 50, false);
373 						shaderControlSlider->setCaption(ActiveShaderDef.Name);
374 
375 						float uniformVal = 0.0;
376 						switch(ActiveShaderDef.ValType)
377 						{
378 							case GPU_VERTEX:
379 							case GPU_FRAGMENT:
380 								{
381 									Ogre::GpuProgramParametersSharedPtr activeParameters =
382 										(ActiveShaderDef.ValType == GPU_VERTEX) ?
383 											mActiveVertexParameters : mActiveFragmentParameters;
384 									if(!activeParameters.isNull())
385 									{
386 										// use param name to get index : use appropriate parameters ptr
387 										const Ogre::GpuConstantDefinition& def =
388 											activeParameters->getConstantDefinition(ActiveShaderDef.ParamName);
389 										ActiveShaderDef.PhysicalIndex = def.physicalIndex;
390 										// use index to get RealConstantEntry
391 										const float* pFloat = activeParameters->getFloatPointer(ActiveShaderDef.PhysicalIndex);
392 										// set position of ScrollWidget as param value
393 										uniformVal = pFloat[ActiveShaderDef.ElementIndex];
394 									}
395 								}
396 								break;
397 
398 							case MAT_SPECULAR:
399 								{
400 									// get the specular values from the material pass
401 
402 									Ogre::ColourValue OldSpec(mActivePass->getSpecular());
403 									uniformVal = OldSpec[ActiveShaderDef.ElementIndex];
404 								}
405 								break;
406 
407 							case MAT_DIFFUSE:
408 								{
409 									// get the diffuse values from the material pass
410 
411 									Ogre::ColourValue OldSpec(mActivePass->getDiffuse());
412 									uniformVal = OldSpec[ActiveShaderDef.ElementIndex];
413 								}
414 								break;
415 
416 							case MAT_AMBIENT:
417 								{
418 									// get the ambient values from the material pass
419 
420 									Ogre::ColourValue OldSpec(mActivePass->getAmbient());
421 									uniformVal = OldSpec[ActiveShaderDef.ElementIndex];
422 								}
423 								break;
424 
425 							case MAT_SHININESS:
426 								{
427 									// get the ambient values from the material pass
428 									uniformVal = mActivePass->getShininess();
429 								}
430 
431 								break;
432 
433 							case MAT_EMISSIVE:
434 								{
435 									// get the ambient values from the material pass
436 
437 									//ColourValue OldSpec(mActivePass->gete());
438 									//activeScrollWidget->setScrollPosition( OldSpec.val[ActiveShaderDef->ElementIndex] );
439 								}
440 								break;
441 						}
442 						shaderControlSlider->setValue(uniformVal);
443 
444 					}
445 					else
446 					{
447 						shaderControlSlider->hide();
448 					}
449 				}
450 			}
451 		}
452 	}
453 
454 }
itemSelected(SelectMenu * menu)455 void Sample_Ocean::itemSelected(SelectMenu *menu)
456 {
457 	//Only one selection menu - the material one
458 	mCurrentMaterial = menu->getSelectionIndex();
459 	mActiveMaterial = Ogre::MaterialManager::getSingleton().getByName( mMaterialControlsContainer[mCurrentMaterial].getMaterialName() );
460 	mActiveMaterial->load();
461 	size_t numShaders = mMaterialControlsContainer[mCurrentMaterial].getShaderControlCount();
462 	mNumPages = (numShaders / CONTROLS_PER_PAGE) + (numShaders % CONTROLS_PER_PAGE == 0 ? 0 : 1);
463 	changePage(0);
464 
465 	if (mOceanSurfaceEnt)
466 	    mOceanSurfaceEnt->setMaterialName(mMaterialControlsContainer[mCurrentMaterial].getMaterialName());
467 }
frameRenderingQueued(const FrameEvent & evt)468 bool Sample_Ocean::frameRenderingQueued(const FrameEvent& evt)
469 {
470 	mRotateSpeed = evt.timeSinceLastFrame * 20;
471 	if(mSpinLight)
472 	{
473 		mLightPivots[0]->rotate(mLightRotationAxes[0], Ogre::Angle(mRotateSpeed * 2.0f));
474 	}
475 	return SdkSample::frameRenderingQueued(evt);
476 }
buttonHit(OgreBites::Button * button)477 void Sample_Ocean::buttonHit(OgreBites::Button* button)
478 {
479 	//Only one button - change page
480 	changePage();
481 }
482 
checkBoxToggled(CheckBox * cb)483 void Sample_Ocean::checkBoxToggled(CheckBox* cb)
484 {
485 	//Only one checkbox
486 	mSpinLight = cb->isChecked();
487 }
488 
489 #endif	// end _Sample_Ocean_H_
490