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