PageRenderTime 57ms CodeModel.GetById 13ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/opengles/src/Light.cpp

http://ftk.googlecode.com/
C++ | 368 lines | 214 code | 92 blank | 62 comment | 36 complexity | 8212d4f1878d570886616afb5b78c9f5 MD5 | raw file
  1// ==========================================================================
  2//
  3// light.cpp	Rendering Context Class for 3D Rendering Library
  4//
  5//				Lightning Related Operations
  6//
  7// --------------------------------------------------------------------------
  8//
  9// 08-07-2003	Hans-Martin Will	initial version
 10//
 11// --------------------------------------------------------------------------
 12//
 13// Copyright (c) 2004, Hans-Martin Will. All rights reserved.
 14// 
 15// Redistribution and use in source and binary forms, with or without 
 16// modification, are permitted provided that the following conditions are 
 17// met:
 18// 
 19//	 *  Redistributions of source code must retain the above copyright
 20// 		notice, this list of conditions and the following disclaimer. 
 21//   *	Redistributions in binary form must reproduce the above copyright
 22// 		notice, this list of conditions and the following disclaimer in the 
 23// 		documentation and/or other materials provided with the distribution. 
 24// 
 25// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 26// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 28// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 29// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
 30// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 31// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 32// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 33// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 34// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
 35// THE POSSIBILITY OF SUCH DAMAGE.
 36//
 37// ==========================================================================
 38
 39
 40#include "stdafx.h"
 41#include "Light.h"
 42#include "Material.h"
 43#include <math.h>
 44
 45
 46#ifndef M_PI
 47#	define M_PI       3.14159265358979323846
 48#endif
 49
 50
 51using namespace EGL;
 52
 53
 54// ==========================================================================
 55// class Light
 56// ==========================================================================
 57
 58
 59Light :: Light() 
 60:	m_AmbientColor(F(0.0f), F(0.0f), F(0.0f), F(1.0f)),
 61	m_DiffuseColor(F(0.0f), F(0.0f), F(0.0f), F(1.0f)),
 62	m_SpecularColor(F(0.0f), F(0.0f), F(0.0f), F(1.0f)),
 63	m_Position(F(0.0f), F(0.0f), F(1.0f), F(0.0f)),
 64	m_SpotDirection(F(0.0f), F(0.0f), F(-1.0f)),
 65	m_NormalizedSpotDirection(F(0.0f), F(0.0f), F(-1.0f)),
 66	m_SpotCutoff(F(180.0f)),
 67	m_ConstantAttenuation(F(1.0f)),
 68	m_LinearAttenuation(0),
 69	m_QuadraticAttenuation(0)
 70{
 71}
 72
 73
 74void Light :: SetAmbientColor(const FractionalColor & color) {
 75	m_AmbientColor = color;
 76}
 77
 78
 79void Light :: SetDiffuseColor(const FractionalColor & color) {
 80	m_DiffuseColor = color;
 81}
 82
 83
 84void Light :: SetSpecularColor(const FractionalColor & color) {
 85	m_SpecularColor = color;
 86}
 87
 88
 89void Light :: SetPosition(const Vec4D & position) {
 90	m_Position = position;
 91}
 92
 93
 94void Light :: SetDirection(const Vec3D & direction) {
 95	m_SpotDirection = m_NormalizedSpotDirection = direction;
 96	m_NormalizedSpotDirection.Normalize();
 97}
 98
 99
100void Light :: SetConstantAttenuation(EGL_Fixed attenuation) {
101	m_ConstantAttenuation = attenuation;
102}
103
104
105void Light :: SetLinearAttenuation(EGL_Fixed attenuation) {
106	m_LinearAttenuation = attenuation;
107}
108
109
110void Light :: SetQuadraticAttenuation(EGL_Fixed attenuation) {
111	m_QuadraticAttenuation = attenuation;
112}
113
114
115void Light :: SetSpotExponent(EGL_Fixed exponent) {
116	m_SpotExponent = exponent;
117}
118
119
120void Light :: SetSpotCutoff(EGL_Fixed cutoff) {
121	m_SpotCutoff = cutoff;
122	EGL_Fixed angle = EGL_Mul(cutoff, EGL_FixedFromFloat(static_cast<float>(M_PI) / 180.0f));
123	m_CosineSpotCutoff = EGL_Cos(angle);
124}
125
126
127void Light :: InitWithMaterial(const Material& material) {
128
129	m_EffectiveAmbientColor = material.GetAmbientColor() * m_AmbientColor;
130	m_EffectiveDiffuseColor = material.GetDiffuseColor() * m_DiffuseColor;
131	m_EffectiveSpecularColor = material.GetSpecularColor() * m_SpecularColor;
132}
133
134// --------------------------------------------------------------------------
135// One-sided lightning calculation
136// --------------------------------------------------------------------------
137
138
139#define EGL_Sqrt EGL_FastSqrt
140
141
142void Light :: AccumulateLight(const Vec4D& vertexCoords, const Vec3D& vertexNormal, 
143							  const Material& currMaterial,
144							  FractionalColor& result) {
145
146	Vec3D vp_li = EGL_Direction(vertexCoords, m_Position);
147	EGL_Fixed sqLength = vp_li.LengthSq();			// keep squared length around for later
148	vp_li.Normalize();								// can optimizer factor this out?
149
150	EGL_Fixed att = EGL_ONE;
151
152	if (m_SpotCutoff != EGL_FixedFromInt(180)) {
153		EGL_Fixed cosine = -(vp_li * m_NormalizedSpotDirection);
154
155		if (cosine < m_CosineSpotCutoff) {
156			return;
157		} else {
158			att = EGL_Power(cosine, m_SpotExponent);
159		}
160	}
161
162	if (m_Position.w() != 0) {
163		EGL_Fixed length = EGL_Sqrt(sqLength);
164
165		att = EGL_Mul(att, EGL_Inverse(m_ConstantAttenuation + 
166			EGL_Mul(m_LinearAttenuation, length) +
167			EGL_Mul(m_QuadraticAttenuation, sqLength)));
168	}
169
170	result.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
171
172	EGL_Fixed diffuseFactor = vertexNormal * vp_li;
173
174	if (diffuseFactor > 0) {
175		result.Accumulate(currMaterial.GetDiffuseColor() * m_DiffuseColor, EGL_Mul(diffuseFactor, att));
176
177			// add specular component
178			// calculate h^
179		Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
180		h.Normalize();
181		EGL_Fixed specularFactor = vertexNormal * h;
182
183		if (specularFactor > 0)
184			result.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor, 
185				EGL_Mul(att, EGL_Power(specularFactor, currMaterial.GetSpecularExponent())));
186	}
187}
188
189
190void Light :: AccumulateLight(const Vec4D& vertexCoords, const Vec3D& vertexNormal, 
191							  const Material& currMaterial,
192							  const FractionalColor & currentColor, 
193							  FractionalColor& result) {
194
195	Vec3D vp_li = EGL_Direction(vertexCoords, m_Position);
196	EGL_Fixed sqLength = vp_li.LengthSq();			// keep squared length around for later
197	vp_li.Normalize();								// can optimizer factor this out?
198
199	EGL_Fixed att = EGL_ONE;
200
201	if (m_SpotCutoff != EGL_FixedFromInt(180)) {
202		EGL_Fixed cosine = -(vp_li * m_NormalizedSpotDirection);
203
204		if (cosine < m_CosineSpotCutoff) {
205			return;
206		} else {
207			att = EGL_Power(cosine, m_SpotExponent);
208		}
209	}
210
211	if (m_Position.w() != 0) {
212		EGL_Fixed length = EGL_Sqrt(sqLength);
213
214		att = EGL_Mul(att, EGL_Inverse(m_ConstantAttenuation + 
215			EGL_Mul(m_LinearAttenuation, length) +
216			EGL_Mul(m_QuadraticAttenuation, sqLength)));
217	}
218
219	result.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
220
221	EGL_Fixed diffuseFactor = vertexNormal * vp_li;
222
223	if (diffuseFactor > 0) {
224		result.Accumulate(currentColor * m_DiffuseColor, EGL_Mul(diffuseFactor, att));
225
226			// add specular component
227			// calculate h^
228		Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
229		h.Normalize();
230		EGL_Fixed specularFactor = vertexNormal * h;
231
232		if (specularFactor > 0)
233			result.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor, 
234				EGL_Mul(att, EGL_Power(specularFactor, currMaterial.GetSpecularExponent())));
235	}
236}
237
238
239// --------------------------------------------------------------------------
240// Two-sided lightning calculation
241// --------------------------------------------------------------------------
242
243void Light :: AccumulateLight2(const Vec4D& vertexCoords, const Vec3D& vertexNormal, 
244							  const Material& currMaterial,
245							  FractionalColor& result, 
246							  FractionalColor& result2) {
247
248	Vec3D vp_li = EGL_Direction(vertexCoords, m_Position);
249	EGL_Fixed sqLength = vp_li.LengthSq();			// keep squared length around for later
250	vp_li.Normalize();								// can optimizer factor this out?
251//either front or back color have to be enabled...
252//	if (diffuseFactor > 0) {
253	EGL_Fixed att = EGL_ONE;
254
255	if (m_SpotCutoff != EGL_FixedFromInt(180)) {
256		EGL_Fixed cosine = -(vp_li * m_NormalizedSpotDirection);
257
258		if (cosine < m_CosineSpotCutoff) {
259			return;
260		} else {
261			att = EGL_Power(cosine, m_SpotExponent);
262		}
263	}
264
265	if (m_Position.w() != 0) {
266		EGL_Fixed length = EGL_Sqrt(sqLength);
267
268		att = EGL_Mul(att, EGL_Inverse(m_ConstantAttenuation + 
269			EGL_Mul(m_LinearAttenuation, length) +
270			EGL_Mul(m_QuadraticAttenuation, sqLength)));
271	}
272
273	result.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
274	result2.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
275
276	EGL_Fixed diffuseFactor = vertexNormal * vp_li;
277
278	if (diffuseFactor > 0) {
279		result.Accumulate(currMaterial.GetDiffuseColor() * m_DiffuseColor, EGL_Mul(diffuseFactor, att));
280
281		// add specular component
282		// calculate h^
283		Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
284		h.Normalize();
285		EGL_Fixed specularFactor = vertexNormal * h;
286
287		if (specularFactor > 0)
288			result.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor, 
289				EGL_Mul(att, EGL_Power(specularFactor, currMaterial.GetSpecularExponent())));
290	} else {
291		result2.Accumulate(currMaterial.GetDiffuseColor() * m_DiffuseColor, EGL_Mul(-diffuseFactor, att));
292
293		Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
294		h.Normalize();
295		EGL_Fixed specularFactor = vertexNormal * h;
296
297		if (specularFactor < 0)
298			result2.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor, 
299				EGL_Mul(att, EGL_Power(-specularFactor, currMaterial.GetSpecularExponent())));
300	}
301
302//	}
303}
304
305
306void Light :: AccumulateLight2(const Vec4D& vertexCoords, const Vec3D& vertexNormal, 
307							  const Material& currMaterial,
308							  const FractionalColor& currentColor,
309							  FractionalColor& result, 
310							  FractionalColor& result2) {
311
312	Vec3D vp_li = EGL_Direction(vertexCoords, m_Position);
313	EGL_Fixed sqLength = vp_li.LengthSq();			// keep squared length around for later
314	vp_li.Normalize();								// can optimizer factor this out?
315
316//either front or back color have to be enabled...
317//	if (diffuseFactor > 0) {
318	EGL_Fixed att = EGL_ONE;
319
320	if (m_SpotCutoff != EGL_FixedFromInt(180)) {
321		EGL_Fixed cosine = -(vp_li * m_NormalizedSpotDirection);
322
323		if (cosine < m_CosineSpotCutoff) {
324			return;
325		} else {
326			att = EGL_Power(cosine, m_SpotExponent);
327		}
328	}
329
330	if (m_Position.w() != 0) {
331		EGL_Fixed length = EGL_Sqrt(sqLength);
332
333		att = EGL_Mul(att, EGL_Inverse(m_ConstantAttenuation + 
334			EGL_Mul(m_LinearAttenuation, length) +
335			EGL_Mul(m_QuadraticAttenuation, sqLength)));
336	}
337
338	result.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
339	result2.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
340
341	EGL_Fixed diffuseFactor = vertexNormal * vp_li;
342
343	if (diffuseFactor > 0) {
344		result.Accumulate(currentColor * m_DiffuseColor, EGL_Mul(diffuseFactor, att));
345			// add specular component
346			// calculate h^
347		Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
348		h.Normalize();
349		EGL_Fixed specularFactor = vertexNormal * h;
350
351		if (specularFactor > 0)
352			result.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor, 
353				EGL_Mul(att, EGL_Power(specularFactor, currMaterial.GetSpecularExponent())));
354	} else {
355		result2.Accumulate(currentColor * m_DiffuseColor, EGL_Mul(-diffuseFactor, att));
356			// add specular component
357			// calculate h^
358		Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
359		h.Normalize();
360		EGL_Fixed specularFactor = vertexNormal * h;
361
362		if (specularFactor < 0)
363			result2.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor, 
364				EGL_Mul(att, EGL_Power(-specularFactor, currMaterial.GetSpecularExponent())));
365	}
366//	}
367}
368