Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/Samples/DeferredShading/src/MLight.cpp @ 5

Last change on this file since 5 was 5, checked in by anonymous, 17 years ago

=hoffentlich gehts jetzt

  • Property svn:executable set to *
File size: 9.4 KB
Line 
1/******************************************************************************
2Copyright (c) W.J. van der Laan
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software  and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to use,
7copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8Software, and to permit persons to whom the Software is furnished to do so, subject
9to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all copies
12or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE
19SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20******************************************************************************/
21#include "MLight.h"
22
23#include "OgreStringConverter.h"
24#include "OgreException.h"
25
26#include "OgreMesh.h"
27#include "OgreSubMesh.h"
28#include "OgreResourceGroupManager.h"
29#include "OgreMeshManager.h"
30#include "OgreHardwareVertexBuffer.h"
31#include "OgreHardwarePixelBuffer.h"
32#include "OgreHardwareBufferManager.h"
33
34#include "OgreRoot.h"
35
36#include "OgreCamera.h"
37
38#include "MaterialGenerator.h"
39
40using namespace Ogre;
41//-----------------------------------------------------------------------
42MLight::MLight(MaterialGenerator *sys):
43        bIgnoreWorld(false), mGenerator(sys),mPermutation(0)
44{
45        // Set up geometry
46        //setMaterial("DeferredShading/Post/LightMaterial");
47        // Set render priority to high (just after normal postprocess)
48        setRenderQueueGroup(RENDER_QUEUE_2);
49        // Allocate render operation
50        mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
51        mRenderOp.indexData = 0;
52        mRenderOp.vertexData = 0;
53        mRenderOp.useIndexes = true;
54
55        // Diffuse and specular colour
56        setDiffuseColour(Ogre::ColourValue(1,1,1));
57        setSpecularColour(Ogre::ColourValue(0,0,0));
58        // Set Attenuation
59        setAttenuation(1.0f,0.0f,0.0f);
60}
61//-----------------------------------------------------------------------
62MLight::~MLight()
63{
64        // need to release IndexData and vertexData created for renderable
65    delete mRenderOp.indexData;
66    delete mRenderOp.vertexData;
67}
68//-----------------------------------------------------------------------
69void MLight::setAttenuation(float c, float b, float a)
70{
71        // Set Attenuation parameter to shader
72        setCustomParameter(3, Vector4(c, b, a, 0));
73
74        /// There is attenuation? Set material accordingly
75        if(c != 1.0f || b != 0.0f || a != 0.0f)
76                mPermutation |= MI_ATTENUATED;
77        else
78                mPermutation &= ~MI_ATTENUATED;
79
80        // Calculate radius from Attenuation
81        int threshold_level = 15;// differece of 10-15 levels deemed unnoticable
82        float threshold = 1.0f/((float)threshold_level/256.0f); 
83
84        // Use quadratic formula to determine outer radius
85        c = c-threshold;
86        float d=sqrt(b*b-4*a*c);
87        float x=(-2*c)/(b+d);
88
89        rebuildGeometry(x);
90}
91//-----------------------------------------------------------------------
92void MLight::setDiffuseColour(const Ogre::ColourValue &col)
93{
94        setCustomParameter(1, Vector4(col.r, col.g, col.b, col.a));
95}
96//-----------------------------------------------------------------------
97void MLight::setSpecularColour(const Ogre::ColourValue &col)
98{
99        setCustomParameter(2, Vector4(col.r, col.g, col.b, col.a));
100        /// There is a specular component? Set material accordingly
101       
102        if(col.r != 0.0f || col.g != 0.0f || col.b != 0.0f)
103                mPermutation |= MI_SPECULAR;
104        else
105                mPermutation &= ~MI_SPECULAR;
106               
107}
108//-----------------------------------------------------------------------
109Ogre::ColourValue MLight::getDiffuseColour()
110{
111        Ogre::Vector4 val = getCustomParameter(1);
112        return Ogre::ColourValue(val[0], val[1], val[2], val[3]);
113}
114//-----------------------------------------------------------------------
115Ogre::ColourValue MLight::getSpecularColour()
116{
117        Ogre::Vector4 val = getCustomParameter(2);
118        return Ogre::ColourValue(val[0], val[1], val[2], val[3]);
119}
120//-----------------------------------------------------------------------
121void MLight::rebuildGeometry(float radius)
122{
123        // Scale node to radius
124       
125        if(radius > 10000.0f)
126        {
127                createRectangle2D();
128                mPermutation |= MI_QUAD;
129        }
130        else
131        {
132                /// XXX some more intelligent expression for rings and segments
133                createSphere(radius, 5, 5);
134                mPermutation &= ~MI_QUAD;
135        }       
136}
137//-----------------------------------------------------------------------
138void MLight::createRectangle2D()
139{
140        /// XXX this RenderOp should really be re-used between MLight objects,
141        /// not generated every time
142        delete mRenderOp.vertexData; 
143        delete mRenderOp.indexData; 
144        mRenderOp.vertexData = new VertexData();
145    mRenderOp.indexData = 0;
146
147    mRenderOp.vertexData->vertexCount = 4; 
148    mRenderOp.vertexData->vertexStart = 0; 
149    mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP; 
150    mRenderOp.useIndexes = false; 
151
152    VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
153    VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding;
154
155    decl->addElement(0, 0, VET_FLOAT3, VES_POSITION);
156
157    HardwareVertexBufferSharedPtr vbuf = 
158        HardwareBufferManager::getSingleton().createVertexBuffer(
159        decl->getVertexSize(0),
160        mRenderOp.vertexData->vertexCount,
161        HardwareBuffer::HBU_STATIC_WRITE_ONLY);
162
163    // Bind buffer
164    bind->setBinding(0, vbuf);
165        // Upload data
166        float data[]={
167                -1,1,-1,  // corner 1
168                -1,-1,-1, // corner 2
169                1,1,-1,   // corner 3
170                1,-1,-1}; // corner 4
171        vbuf->writeData(0, sizeof(data), data, true);
172
173        // Set bounding
174    setBoundingBox(AxisAlignedBox(-10000,-10000,-10000,10000,10000,10000));
175        mRadius = 15000;
176        bIgnoreWorld = true;
177}
178//-----------------------------------------------------------------------
179void MLight::createSphere(const float r, const int nRings, const int nSegments)
180{
181        delete mRenderOp.vertexData; 
182        delete mRenderOp.indexData;
183        mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
184        mRenderOp.indexData = new IndexData();
185        mRenderOp.vertexData = new VertexData();
186        mRenderOp.useIndexes = true;
187
188        VertexData* vertexData = mRenderOp.vertexData;
189        IndexData* indexData = mRenderOp.indexData;
190
191        // define the vertex format
192        VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
193        size_t currOffset = 0;
194        // only generate positions
195        vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
196        currOffset += VertexElement::getTypeSize(VET_FLOAT3);
197        // allocate the vertex buffer
198        vertexData->vertexCount = (nRings + 1) * (nSegments+1);
199        HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
200        VertexBufferBinding* binding = vertexData->vertexBufferBinding;
201        binding->setBinding(0, vBuf);
202        float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD));
203
204        // allocate index buffer
205        indexData->indexCount = 6 * nRings * (nSegments + 1);
206        indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
207        HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer;
208        unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD));
209
210        float fDeltaRingAngle = (Math::PI / nRings);
211        float fDeltaSegAngle = (2 * Math::PI / nSegments);
212        unsigned short wVerticeIndex = 0 ;
213
214        // Generate the group of rings for the sphere
215        for( int ring = 0; ring <= nRings; ring++ ) {
216                float r0 = r * sinf (ring * fDeltaRingAngle);
217                float y0 = r * cosf (ring * fDeltaRingAngle);
218
219                // Generate the group of segments for the current ring
220                for(int seg = 0; seg <= nSegments; seg++) {
221                        float x0 = r0 * sinf(seg * fDeltaSegAngle);
222                        float z0 = r0 * cosf(seg * fDeltaSegAngle);
223
224                        // Add one vertex to the strip which makes up the sphere
225                        *pVertex++ = x0;
226                        *pVertex++ = y0;
227                        *pVertex++ = z0;
228
229                        if (ring != nRings) 
230                        {
231                // each vertex (except the last) has six indicies pointing to it
232                                *pIndices++ = wVerticeIndex + nSegments + 1;
233                                *pIndices++ = wVerticeIndex;               
234                                *pIndices++ = wVerticeIndex + nSegments;
235                                *pIndices++ = wVerticeIndex + nSegments + 1;
236                                *pIndices++ = wVerticeIndex + 1;
237                                *pIndices++ = wVerticeIndex;
238                                wVerticeIndex ++;
239                        }
240                }; // end for seg
241        } // end for ring
242
243        // Unlock
244        vBuf->unlock();
245        iBuf->unlock();
246
247        // Set bounding box and sphere
248        setBoundingBox( AxisAlignedBox( Vector3(-r, -r, -r), Vector3(r, r, r) ) );
249        mRadius = r;
250        bIgnoreWorld = false;
251}                                                               
252//-----------------------------------------------------------------------
253Real MLight::getBoundingRadius(void) const
254{
255        return mRadius;
256}
257//-----------------------------------------------------------------------
258Ogre::Real MLight::getSquaredViewDepth(const Ogre::Camera* cam) const
259{
260        if(bIgnoreWorld)
261        {
262                return 0.0f;
263        }
264        else
265        {
266                Vector3 dist = cam->getDerivedPosition() - getWorldPosition();                                                                       
267                return dist.squaredLength();
268        }
269}
270//-----------------------------------------------------------------------
271const MaterialPtr& MLight::getMaterial(void) const
272{
273        return mGenerator->getMaterial(mPermutation);
274}
Note: See TracBrowser for help on using the repository browser.