--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/m3g/m3gcore11/src/m3g_material.c Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,375 @@
+/*
+* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Material implementation
+*
+*/
+
+
+/*!
+ * \internal
+ * \file
+ * \brief Material implementation
+ */
+
+#ifndef M3G_CORE_INCLUDE
+# error included by m3g_core.c; do not compile separately.
+#endif
+
+#include "m3g_material.h"
+#include "m3g_animationtrack.h"
+
+#define ALL_TARGET_MASK (M3G_AMBIENT_BIT | M3G_DIFFUSE_BIT | M3G_EMISSIVE_BIT | M3G_SPECULAR_BIT)
+
+/*----------------------------------------------------------------------
+ * Internal functions
+ *--------------------------------------------------------------------*/
+
+/*!
+ * \internal
+ * \brief Applies default material to OpenGL.
+ */
+static void m3gApplyDefaultMaterial(void)
+{
+ glDisable(GL_COLOR_MATERIAL);
+ glDisable(GL_LIGHTING);
+}
+
+/*!
+ * \internal
+ * \brief Applies material to OpenGL.
+ *
+ * \param material Material object
+ * \param alphaFactor alpha factor as 1.16 fixed point
+ */
+static void m3gApplyMaterial(Material *material, M3Gint alphaFactor)
+{
+ if (material != NULL) {
+ M3Gfloat colors[4];
+
+ /* NOTE We must set the ColorMaterial state *before* setting
+ * any of the material colors, as they will not change if
+ * tracking is enabled! */
+
+ if (material->vertexColorTracking) {
+ glEnable(GL_COLOR_MATERIAL);
+ }
+ else {
+ glDisable(GL_COLOR_MATERIAL);
+
+ /* Ambient and diffuse only need to be set when tracking
+ * is disabled */
+
+ m3gFloatColor(material->ambientColor, 1.0f, colors);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, colors);
+ m3gFloatColor(material->diffuseColor, 1.0f, colors);
+ if (alphaFactor < 0x10000) {
+ colors[3] = m3gMul(colors[3],
+ m3gMul((M3Gfloat) alphaFactor,
+ 1.f/65536.f));
+ }
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, colors);
+ }
+ m3gFloatColor(material->emissiveColor, 1.0f, colors);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, colors);
+ m3gFloatColor(material->specularColor, 1.0f, colors);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, colors);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material->shininess);
+
+ glEnable(GL_LIGHTING);
+ }
+ else {
+ m3gApplyDefaultMaterial();
+ }
+ M3G_ASSERT_GL;
+}
+
+/*!
+ * \internal
+ * \brief Overloaded Object3D method.
+ *
+ * \param property animation property
+ * \retval M3G_TRUE property supported
+ * \retval M3G_FALSE property not supported
+ */
+static M3Gbool m3gMaterialIsCompatible(M3Gint property)
+{
+ switch (property) {
+ case M3G_ANIM_ALPHA:
+ case M3G_ANIM_AMBIENT_COLOR:
+ case M3G_ANIM_DIFFUSE_COLOR:
+ case M3G_ANIM_EMISSIVE_COLOR:
+ case M3G_ANIM_SHININESS:
+ case M3G_ANIM_SPECULAR_COLOR:
+ return M3G_TRUE;
+ default:
+ return m3gObjectIsCompatible(property);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Overloaded Object3D method.
+ *
+ * \param self Material object
+ * \param property animation property
+ * \param valueSize size of value array
+ * \param value value array
+ */
+static void m3gMaterialUpdateProperty(Object *self,
+ M3Gint property,
+ M3Gint valueSize,
+ const M3Gfloat *value)
+{
+ Material *material = (Material *)self;
+ M3G_VALIDATE_OBJECT(material);
+ M3G_ASSERT_PTR(value);
+
+ switch (property) {
+ case M3G_ANIM_ALPHA:
+ M3G_ASSERT(valueSize >= 1);
+ material->diffuseColor = (material->diffuseColor | M3G_ALPHA_MASK) &
+ m3gAlpha1f(value[0]);
+ break;
+ case M3G_ANIM_AMBIENT_COLOR:
+ M3G_ASSERT(valueSize >= 3);
+ material->ambientColor = m3gColor3f(value[0], value[1], value[2]);
+ break;
+ case M3G_ANIM_DIFFUSE_COLOR:
+ M3G_ASSERT(valueSize >= 3);
+ material->diffuseColor = (material->diffuseColor | M3G_RGB_MASK)
+ & m3gColor3f(value[0], value[1], value[2]);
+ break;
+ case M3G_ANIM_EMISSIVE_COLOR:
+ M3G_ASSERT(valueSize >= 3);
+ material->emissiveColor = m3gColor3f(value[0], value[1], value[2]) & M3G_RGB_MASK;
+ break;
+ case M3G_ANIM_SHININESS:
+ M3G_ASSERT(valueSize >= 1);
+ material->shininess = m3gClampFloat(value[0], 0.f, 128.f);
+ break;
+ case M3G_ANIM_SPECULAR_COLOR:
+ M3G_ASSERT(valueSize >= 3);
+ material->specularColor = m3gColor3f(value[0], value[1], value[2]);
+ break;
+ default:
+ m3gObjectUpdateProperty(self, property, valueSize, value);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Overloaded Object3D method.
+ *
+ * \param originalObj original Material object
+ * \param cloneObj pointer to cloned Material object
+ * \param pairs array for all object-duplicate pairs
+ * \param numPairs number of pairs
+ */
+static M3Gbool m3gMaterialDuplicate(const Object *originalObj,
+ Object **cloneObj,
+ Object **pairs,
+ M3Gint *numPairs)
+{
+ const Material *original = (const Material *)originalObj;
+
+ /* Create the clone object */
+
+ Material *clone = (Material *)m3gCreateMaterial(originalObj->interface);
+ if (!clone) {
+ return M3G_FALSE;
+ }
+ *cloneObj = (Object *)clone;
+
+ /* Duplicate base class and own data */
+
+ if (m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
+ clone->vertexColorTracking = original->vertexColorTracking;
+ clone->ambientColor = original->ambientColor;
+ clone->diffuseColor = original->diffuseColor;
+ clone->emissiveColor = original->emissiveColor;
+ clone->specularColor = original->specularColor;
+ clone->shininess = original->shininess;
+ return M3G_TRUE;
+ }
+ else {
+ return M3G_FALSE;
+ }
+}
+
+/*----------------------------------------------------------------------
+ * Virtual function table
+ *--------------------------------------------------------------------*/
+
+static const ObjectVFTable m3gvf_Material = {
+ m3gObjectApplyAnimation,
+ m3gMaterialIsCompatible,
+ m3gMaterialUpdateProperty,
+ m3gObjectDoGetReferences,
+ m3gObjectFindID,
+ m3gMaterialDuplicate,
+ m3gDestroyObject
+};
+
+
+/*----------------------------------------------------------------------
+ * Public API functions
+ *--------------------------------------------------------------------*/
+
+/*!
+ * \brief Creates a Material object.
+ *
+ * \param interface M3G interface
+ * \retval Material new Material object
+ * \retval NULL Material creating failed
+ */
+M3G_API M3GMaterial m3gCreateMaterial(M3GInterface interface)
+{
+ Interface *m3g = (Interface *) interface;
+ M3G_VALIDATE_INTERFACE(m3g);
+
+ {
+ Material *material = m3gAllocZ(m3g, sizeof(Material));
+
+ if (material != NULL) {
+ m3gInitObject(&material->object, m3g, M3G_CLASS_MATERIAL);
+ /* Default values are from the jsr-184 specification */
+ material->vertexColorTracking = GL_FALSE;
+ material->ambientColor = 0x00333333U;
+ material->diffuseColor = 0xFFCCCCCCU;
+ material->emissiveColor = 0x00000000U;
+ material->specularColor = 0x00000000U;
+ material->shininess = 0.0f;
+ }
+
+ return (M3GMaterial)material;
+ }
+}
+
+/*!
+ * \brief Set material color.
+ *
+ * \param hMaterial Material object
+ * \param target color target
+ * \param ARGB ARGB color
+ */
+M3G_API void m3gSetColor(M3GMaterial hMaterial, M3Genum target, M3Guint ARGB)
+{
+ Material *material = (Material *) hMaterial;
+ M3G_VALIDATE_OBJECT(material);
+ /* is invalid target in the mask OR no target */
+ if (((target | ALL_TARGET_MASK) != ALL_TARGET_MASK) || ((target & ALL_TARGET_MASK) == 0)) {
+ m3gRaiseError(M3G_INTERFACE(material), M3G_INVALID_VALUE);
+ return;
+ }
+ if ((target & M3G_AMBIENT_BIT) != 0) {
+ material->ambientColor = ARGB & M3G_RGB_MASK;
+ }
+ if ((target & M3G_DIFFUSE_BIT) != 0) {
+ material->diffuseColor = ARGB;
+ }
+ if ((target & M3G_EMISSIVE_BIT) != 0) {
+ material->emissiveColor = ARGB & M3G_RGB_MASK;
+ }
+ if ((target & M3G_SPECULAR_BIT) != 0) {
+ material->specularColor = ARGB & M3G_RGB_MASK;
+ }
+}
+
+/*!
+ * \brief Get material color.
+ *
+ * \param hMaterial Material object
+ * \param target color target
+ * \return ARGB color
+ */
+M3G_API M3Guint m3gGetColor(M3GMaterial hMaterial, M3Genum target)
+{
+ Material *material = (Material *) hMaterial;
+ M3G_VALIDATE_OBJECT(material);
+
+ switch (target) {
+ case M3G_AMBIENT_BIT:
+ return material->ambientColor;
+ case M3G_DIFFUSE_BIT:
+ return material->diffuseColor;
+ case M3G_EMISSIVE_BIT:
+ return material->emissiveColor;
+ case M3G_SPECULAR_BIT:
+ return material->specularColor;
+ default:
+ m3gRaiseError(M3G_INTERFACE(material), M3G_INVALID_VALUE);
+ break;
+ }
+
+ return 0; /* Error */
+}
+
+/*!
+ * \brief Set material shininess.
+ *
+ * \param hMaterial Material object
+ * \param shininess shininess
+ */
+M3G_API void m3gSetShininess(M3GMaterial hMaterial, M3Gfloat shininess)
+{
+ Material *material = (Material *) hMaterial;
+ M3G_VALIDATE_OBJECT(material);
+ if (!m3gInRangef(shininess, 0.0f, 128.f)) {
+ m3gRaiseError(M3G_INTERFACE(material), M3G_INVALID_VALUE);
+ return;
+ }
+ material->shininess = shininess;
+}
+
+/*!
+ * \brief Get material shininess.
+ *
+ * \param hMaterial Material object
+ * \return shininess
+ */
+M3G_API GLfloat m3gGetShininess(M3GMaterial hMaterial)
+{
+ Material *material = (Material *) hMaterial;
+ M3G_VALIDATE_OBJECT(material);
+ return material->shininess;
+}
+
+/*!
+ * \brief Set vertex color tracking enable.
+ *
+ * \param hMaterial Material object
+ * \param enable color tracking enable
+ */
+M3G_API void m3gSetVertexColorTrackingEnable(M3GMaterial hMaterial,
+ M3Gbool enable)
+{
+ Material *material = (Material *) hMaterial;
+ M3G_VALIDATE_OBJECT(material);
+ material->vertexColorTracking = (GLboolean) enable;
+}
+
+/*!
+ * \brief Get vertex color tracking enable.
+ *
+ * \param hMaterial Material object
+ * \retval M3G_TRUE color tracking enabled
+ * \retval M3G_FALSE color tracking disabled
+ */
+M3G_API M3Gbool m3gIsVertexColorTrackingEnabled(M3GMaterial hMaterial)
+{
+ Material *material = (Material *) hMaterial;
+ M3G_VALIDATE_OBJECT(material);
+ return (M3Gbool) material->vertexColorTracking;
+}
+