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-2014 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 #include "VolumeTex.h"
16
17 #include "OgreTexture.h"
18 #include "OgreHardwarePixelBuffer.h"
19 #include "OgreTextureManager.h"
20 #include "OgreLogManager.h"
21 #include <sstream>
22
23 #include "VolumeRenderable.h"
24 #include "ThingRenderable.h"
25 #include "Julia.h"
26
27 namespace {
28 SimpleRenderable *vrend;
29 SimpleRenderable *trend;
30 SceneNode *snode,*fnode;
31 }
32
setupContent()33 void Sample_VolumeTex::setupContent()
34 {
35 if (!ResourceGroupManager::getSingleton().resourceGroupExists("VolumeRenderable"))
36 {
37 ResourceGroupManager::getSingleton().createResourceGroup("VolumeRenderable");
38 }
39 // Create dynamic texture
40 ptex = TextureManager::getSingleton().createManual(
41 "DynaTex","VolumeRenderable", TEX_TYPE_3D, 64, 64, 64, 0, PF_BYTE_RGBA);
42
43 // Set ambient light
44 mSceneMgr->setAmbientLight(ColourValue(0.6, 0.6, 0.6));
45 mSceneMgr->setSkyBox(true, "Examples/MorningSkyBox", 50 );
46
47 //mRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR, ColourValue(255,255,255,0));
48
49 // Create a light
50 Light* l = mSceneMgr->createLight("MainLight");
51 l->setDiffuseColour(0.75, 0.75, 0.80);
52 l->setSpecularColour(0.9, 0.9, 1);
53 mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-100,80,50))->attachObject(l);
54
55 // Create volume renderable
56 snode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,0,0));
57
58 vrend = new VolumeRenderable(32, 750.0f, "DynaTex");
59 snode->attachObject( vrend );
60
61 trend = new ThingRenderable(90.0f, 32, 7.5f);
62 MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/VTDarkStuff", "General");
63 trend->setMaterial(mat);
64 snode->attachObject(trend);
65
66 // Ogre head node
67 fnode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,0,0));
68 // Load ogre head
69 Entity* head = mSceneMgr->createEntity("head", "ogrehead.mesh");
70 fnode->attachObject(head);
71
72 // Animation for ogre head
73 // Create a track for the light
74 Animation* anim = mSceneMgr->createAnimation("OgreTrack", 10);
75 // Spline it for nice curves
76 anim->setInterpolationMode(Animation::IM_SPLINE);
77 // Create a track to animate the camera's node
78 NodeAnimationTrack* track = anim->createNodeTrack(0, fnode);
79 // Setup keyframes
80 TransformKeyFrame* key = track->createNodeKeyFrame(0); // A startposition
81 key->setTranslate(Vector3(0.0f, -15.0f, 0.0f));
82 key = track->createNodeKeyFrame(5);//B
83 key->setTranslate(Vector3(0.0f, 15.0f, 0.0f));
84 key = track->createNodeKeyFrame(10);//C
85 key->setTranslate(Vector3(0.0f, -15.0f, 0.0f));
86 // Create a new animation state to track this
87 auto animState = mSceneMgr->createAnimationState("OgreTrack");
88 animState->setEnabled(true);
89 auto& controllerMgr = ControllerManager::getSingleton();
90 controllerMgr.createFrameTimePassthroughController(AnimationStateControllerValue::create(animState, true));
91
92 //mFountainNode->attachObject(pSys2);
93
94 //Setup defaults
95 global_real = 0.4f;
96 global_imag = 0.6f;
97 global_theta = 0.0f;
98
99 // show GUI
100 createControls();
101
102 mCameraMan->setStyle(CS_ORBIT);
103
104 generate();
105 }
106
frameRenderingQueued(const FrameEvent & evt)107 bool Sample_VolumeTex::frameRenderingQueued(const FrameEvent &evt)
108 {
109 //snode->roll(Degree(evt.timeSinceLastFrame * 20.0f));
110 //fnode->roll(Degree(evt.timeSinceLastFrame * 20.0f));
111 static_cast<ThingRenderable*>(trend)->addTime(evt.timeSinceLastFrame * 0.05f);
112 return SdkSample::frameRenderingQueued(evt);
113 }
114
cleanupContent()115 void Sample_VolumeTex::cleanupContent()
116 {
117 TextureManager::getSingleton().remove("DynaTex", "VolumeRenderable");
118 delete vrend;
119 delete trend;
120 }
121
generate()122 void Sample_VolumeTex::generate()
123 {
124 /* Evaluate julia fractal for each point */
125 Julia julia(global_real, global_imag, global_theta);
126 const float scale = 2.5;
127 const float vcut = 29.0f;
128 const float vscale = 1.0f/vcut;
129
130 HardwarePixelBufferSharedPtr buffer = ptex->getBuffer(0, 0);
131 Ogre::StringStream d;
132 d << "HardwarePixelBuffer " << buffer->getWidth() << " " << buffer->getHeight() << " " << buffer->getDepth();
133 LogManager::getSingleton().logMessage(d.str());
134
135 buffer->lock(HardwareBuffer::HBL_NORMAL);
136 const PixelBox &pb = buffer->getCurrentLock();
137 d.str("");
138 d << "PixelBox " << pb.getWidth() << " " << pb.getHeight() << " " << pb.getDepth() << " " << pb.rowPitch << " " << pb.slicePitch << " " << pb.data << " " << PixelUtil::getFormatName(pb.format);
139 LogManager::getSingleton().logMessage(d.str());
140
141 Ogre::uint32 *pbptr = reinterpret_cast<Ogre::uint32*>(pb.data);
142 for(size_t z=pb.front; z<pb.back; z++)
143 {
144 for(size_t y=pb.top; y<pb.bottom; y++)
145 {
146 for(size_t x=pb.left; x<pb.right; x++)
147 {
148 if(z==pb.front || z==(pb.back-1) || y==pb.top|| y==(pb.bottom-1) ||
149 x==pb.left || x==(pb.right-1))
150 {
151 // On border, must be zero
152 pbptr[x] = 0;
153 }
154 else
155 {
156 float val = julia.eval(((float)x/pb.getWidth()-0.5f) * scale,
157 ((float)y/pb.getHeight()-0.5f) * scale,
158 ((float)z/pb.getDepth()-0.5f) * scale);
159 if(val > vcut)
160 val = vcut;
161
162 PixelUtil::packColour((float)x/pb.getWidth(), (float)y/pb.getHeight(), (float)z/pb.getDepth(), (1.0f-(val*vscale))*0.7f, PF_BYTE_RGBA, &pbptr[x]);
163
164 }
165 }
166 pbptr += pb.rowPitch;
167 }
168 pbptr += pb.getSliceSkip();
169 }
170 buffer->unlock();
171 }
172