sl@0
|
1 |
/*
|
sl@0
|
2 |
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
3 |
* All rights reserved.
|
sl@0
|
4 |
* This component and the accompanying materials are made available
|
sl@0
|
5 |
* under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
6 |
* which accompanies this distribution, and is available
|
sl@0
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
8 |
*
|
sl@0
|
9 |
* Initial Contributors:
|
sl@0
|
10 |
* Nokia Corporation - initial contribution.
|
sl@0
|
11 |
*
|
sl@0
|
12 |
* Contributors:
|
sl@0
|
13 |
*
|
sl@0
|
14 |
* Description: Appearance implementation
|
sl@0
|
15 |
*
|
sl@0
|
16 |
*/
|
sl@0
|
17 |
|
sl@0
|
18 |
|
sl@0
|
19 |
/*!
|
sl@0
|
20 |
* \internal
|
sl@0
|
21 |
* \file
|
sl@0
|
22 |
* \brief Appearance implementation
|
sl@0
|
23 |
*/
|
sl@0
|
24 |
|
sl@0
|
25 |
#ifndef M3G_CORE_INCLUDE
|
sl@0
|
26 |
# error included by m3g_core.c; do not compile separately.
|
sl@0
|
27 |
#endif
|
sl@0
|
28 |
|
sl@0
|
29 |
#include "m3g_appearance.h"
|
sl@0
|
30 |
#include "m3g_vertexbuffer.h"
|
sl@0
|
31 |
|
sl@0
|
32 |
/*----------------------------------------------------------------------
|
sl@0
|
33 |
* Private functions
|
sl@0
|
34 |
*--------------------------------------------------------------------*/
|
sl@0
|
35 |
|
sl@0
|
36 |
/*!
|
sl@0
|
37 |
* \internal
|
sl@0
|
38 |
* \brief Applies default appearance values to OpenGL.
|
sl@0
|
39 |
*/
|
sl@0
|
40 |
static void m3gApplyAppearanceDefaults(RenderContext *ctx)
|
sl@0
|
41 |
{
|
sl@0
|
42 |
int i;
|
sl@0
|
43 |
m3gApplyCompositingMode(NULL, ctx);
|
sl@0
|
44 |
m3gApplyPolygonMode(NULL);
|
sl@0
|
45 |
m3gApplyMaterial(NULL, 0x10000);
|
sl@0
|
46 |
m3gApplyFog(NULL);
|
sl@0
|
47 |
|
sl@0
|
48 |
for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
|
sl@0
|
49 |
glActiveTexture(GL_TEXTURE0 + i);
|
sl@0
|
50 |
glDisable(GL_TEXTURE_2D);
|
sl@0
|
51 |
}
|
sl@0
|
52 |
}
|
sl@0
|
53 |
|
sl@0
|
54 |
/*!
|
sl@0
|
55 |
* \internal
|
sl@0
|
56 |
* \brief Generate a hash number for a pointer
|
sl@0
|
57 |
*/
|
sl@0
|
58 |
static M3Guint m3gGenPointerHash(const void *ptr)
|
sl@0
|
59 |
{
|
sl@0
|
60 |
M3Guint p = ((M3Guint) ptr) >> 2;
|
sl@0
|
61 |
M3Guint key = p ^ (p >> 5) ^ (p >> 10) ^ (p >> 15) ^ (p >> 20) ^ (p >> 25);
|
sl@0
|
62 |
return key;
|
sl@0
|
63 |
}
|
sl@0
|
64 |
|
sl@0
|
65 |
/*!
|
sl@0
|
66 |
* \internal
|
sl@0
|
67 |
* \brief Generate a quick hash bit pattern for the textures of this
|
sl@0
|
68 |
* appearance object
|
sl@0
|
69 |
*/
|
sl@0
|
70 |
static M3Guint m3gGen12BitTextureHash(const Appearance *app)
|
sl@0
|
71 |
{
|
sl@0
|
72 |
M3Guint key = 0;
|
sl@0
|
73 |
|
sl@0
|
74 |
int i;
|
sl@0
|
75 |
|
sl@0
|
76 |
for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
|
sl@0
|
77 |
const Texture *tex = app->texture[i];
|
sl@0
|
78 |
if (tex) {
|
sl@0
|
79 |
key ^= (m3gGenPointerHash(m3gGetTextureImage((M3GTexture)tex)) >> i) << 6;
|
sl@0
|
80 |
key ^= (m3gGenPointerHash(tex) >> i) & 0x3Fu;
|
sl@0
|
81 |
}
|
sl@0
|
82 |
}
|
sl@0
|
83 |
return key & ((1u<<12)-1);
|
sl@0
|
84 |
}
|
sl@0
|
85 |
|
sl@0
|
86 |
/*!
|
sl@0
|
87 |
* \internal
|
sl@0
|
88 |
* \brief Generate the sorting key for render queue
|
sl@0
|
89 |
*
|
sl@0
|
90 |
* Sort key is a combination of user settable layer and
|
sl@0
|
91 |
* blending mode. Blended objects are always drawn last.
|
sl@0
|
92 |
*
|
sl@0
|
93 |
* \param appearance Appearance object
|
sl@0
|
94 |
* \return sort key
|
sl@0
|
95 |
*/
|
sl@0
|
96 |
static void m3gRegenerateSortKey(Appearance *appearance)
|
sl@0
|
97 |
{
|
sl@0
|
98 |
M3Guint key = 0;
|
sl@0
|
99 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
100 |
|
sl@0
|
101 |
/*------------------------------------------------------------
|
sl@0
|
102 |
* First do the mandatory sorting by layer index and blending
|
sl@0
|
103 |
* state; this currently uses the top eight bits, 31..24
|
sl@0
|
104 |
*-----------------------------------------------------------*/
|
sl@0
|
105 |
|
sl@0
|
106 |
key = (appearance->layer - M3G_APPEARANCE_MIN_LAYER)
|
sl@0
|
107 |
<< (33 - M3G_APPEARANCE_HARD_SORT_BITS);
|
sl@0
|
108 |
|
sl@0
|
109 |
/* NOTE the blending state bit is not set here, but dynamically in
|
sl@0
|
110 |
* m3gGetAppearanceSortKey; this way we do not need to implement
|
sl@0
|
111 |
* signaling from CompositingMode to Appearance when the blending
|
sl@0
|
112 |
* state changes */
|
sl@0
|
113 |
|
sl@0
|
114 |
/*-----------------------------------------------------------------
|
sl@0
|
115 |
* The rest of the bits, 23..0, affect performance only; ideally,
|
sl@0
|
116 |
* these should be sorted so that the more expensive state is in the
|
sl@0
|
117 |
* higher bits, but this is largely dependent on the hardware
|
sl@0
|
118 |
*----------------------------------------------------------------*/
|
sl@0
|
119 |
|
sl@0
|
120 |
/* Texturing changes are often expensive in graphics hardware, so
|
sl@0
|
121 |
* we put a hash of the texture objects into the top twelve
|
sl@0
|
122 |
* bits
|
sl@0
|
123 |
*
|
sl@0
|
124 |
* NOTE we do not currently update this if a texture image
|
sl@0
|
125 |
* changes, but that shouldn't happen too often and only has
|
sl@0
|
126 |
* relatively minor performance implications
|
sl@0
|
127 |
*/
|
sl@0
|
128 |
|
sl@0
|
129 |
key |= m3gGen12BitTextureHash(appearance) << 12;
|
sl@0
|
130 |
|
sl@0
|
131 |
/* Use the rest of the bits for the various components; depth
|
sl@0
|
132 |
* function changes are another potentially costly operation, so
|
sl@0
|
133 |
* put that next */
|
sl@0
|
134 |
|
sl@0
|
135 |
key |= (m3gGenPointerHash(appearance->compositingMode) & 0x0Fu) << 8;
|
sl@0
|
136 |
key |= (m3gGenPointerHash(appearance->material) & 0x07u) << 5;
|
sl@0
|
137 |
key |= (m3gGenPointerHash(appearance->polygonMode) & 0x07u) << 2;
|
sl@0
|
138 |
key |= (m3gGenPointerHash(appearance->fog) & 0x03u);
|
sl@0
|
139 |
|
sl@0
|
140 |
/* Store the final value */
|
sl@0
|
141 |
appearance->sortKey = key;
|
sl@0
|
142 |
}
|
sl@0
|
143 |
|
sl@0
|
144 |
/*----------------------------------------------------------------------
|
sl@0
|
145 |
* Internal functions
|
sl@0
|
146 |
*--------------------------------------------------------------------*/
|
sl@0
|
147 |
|
sl@0
|
148 |
/*!
|
sl@0
|
149 |
* \internal
|
sl@0
|
150 |
* \brief Destroys this Appearance object.
|
sl@0
|
151 |
*
|
sl@0
|
152 |
* \param obj Appearance object
|
sl@0
|
153 |
*/
|
sl@0
|
154 |
static void m3gDestroyAppearance(Object *obj)
|
sl@0
|
155 |
{
|
sl@0
|
156 |
int i;
|
sl@0
|
157 |
Appearance *appearance = (Appearance *) obj;
|
sl@0
|
158 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
159 |
|
sl@0
|
160 |
M3G_ASSIGN_REF(appearance->compositingMode, NULL);
|
sl@0
|
161 |
M3G_ASSIGN_REF(appearance->fog, NULL);
|
sl@0
|
162 |
M3G_ASSIGN_REF(appearance->material, NULL);
|
sl@0
|
163 |
M3G_ASSIGN_REF(appearance->polygonMode, NULL);
|
sl@0
|
164 |
for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
|
sl@0
|
165 |
M3G_ASSIGN_REF(appearance->texture[i], NULL);
|
sl@0
|
166 |
}
|
sl@0
|
167 |
|
sl@0
|
168 |
m3gDestroyObject(obj);
|
sl@0
|
169 |
}
|
sl@0
|
170 |
|
sl@0
|
171 |
/*!
|
sl@0
|
172 |
* \internal
|
sl@0
|
173 |
* \brief Applies Apperance settings to current OpenGL state
|
sl@0
|
174 |
*
|
sl@0
|
175 |
* \note m3gReleaseTextures must be called when no longer using this,
|
sl@0
|
176 |
* to properly reset texture usage counters and unmap the texture
|
sl@0
|
177 |
* images.
|
sl@0
|
178 |
*
|
sl@0
|
179 |
* \param appearance Appearance object
|
sl@0
|
180 |
* \param alphaFactor alpha factor as 1.16 fixed point
|
sl@0
|
181 |
*/
|
sl@0
|
182 |
static void m3gApplyAppearance(const Appearance *appearance,
|
sl@0
|
183 |
RenderContext *ctx,
|
sl@0
|
184 |
M3Gint alphaFactor)
|
sl@0
|
185 |
{
|
sl@0
|
186 |
M3G_ASSERT_GL;
|
sl@0
|
187 |
|
sl@0
|
188 |
if (appearance != NULL) {
|
sl@0
|
189 |
int i;
|
sl@0
|
190 |
|
sl@0
|
191 |
# if defined(M3G_NGL_TEXTURE_API)
|
sl@0
|
192 |
m3gLockMemory(M3G_INTERFACE(appearance)); /* for textures */
|
sl@0
|
193 |
# endif
|
sl@0
|
194 |
|
sl@0
|
195 |
m3gApplyCompositingMode(appearance->compositingMode, ctx);
|
sl@0
|
196 |
m3gApplyPolygonMode(appearance->polygonMode);
|
sl@0
|
197 |
m3gApplyMaterial(appearance->material, alphaFactor);
|
sl@0
|
198 |
m3gApplyFog(appearance->fog);
|
sl@0
|
199 |
|
sl@0
|
200 |
for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
|
sl@0
|
201 |
Texture *tex = appearance->texture[i];
|
sl@0
|
202 |
glActiveTexture(GL_TEXTURE0 + i);
|
sl@0
|
203 |
if (tex != NULL) {
|
sl@0
|
204 |
glEnable(GL_TEXTURE_2D);
|
sl@0
|
205 |
m3gBindTexture(appearance->texture[i]);
|
sl@0
|
206 |
}
|
sl@0
|
207 |
else {
|
sl@0
|
208 |
glDisable(GL_TEXTURE_2D);
|
sl@0
|
209 |
}
|
sl@0
|
210 |
}
|
sl@0
|
211 |
}
|
sl@0
|
212 |
else {
|
sl@0
|
213 |
m3gApplyAppearanceDefaults(ctx);
|
sl@0
|
214 |
}
|
sl@0
|
215 |
|
sl@0
|
216 |
M3G_ASSERT_GL;
|
sl@0
|
217 |
}
|
sl@0
|
218 |
|
sl@0
|
219 |
/*!
|
sl@0
|
220 |
* \internal
|
sl@0
|
221 |
* \brief Release the textures bound for this appearance
|
sl@0
|
222 |
*/
|
sl@0
|
223 |
static void m3gReleaseTextures(const Appearance *appearance)
|
sl@0
|
224 |
{
|
sl@0
|
225 |
if (appearance != NULL) {
|
sl@0
|
226 |
int i;
|
sl@0
|
227 |
|
sl@0
|
228 |
for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
|
sl@0
|
229 |
Texture *tex = appearance->texture[i];
|
sl@0
|
230 |
if (tex != NULL) {
|
sl@0
|
231 |
m3gReleaseTexture(tex);
|
sl@0
|
232 |
}
|
sl@0
|
233 |
}
|
sl@0
|
234 |
|
sl@0
|
235 |
# if defined(M3G_NGL_TEXTURE_API)
|
sl@0
|
236 |
m3gUnlockMemory(M3G_INTERFACE(appearance));
|
sl@0
|
237 |
# endif
|
sl@0
|
238 |
}
|
sl@0
|
239 |
}
|
sl@0
|
240 |
|
sl@0
|
241 |
/*!
|
sl@0
|
242 |
* \internal
|
sl@0
|
243 |
* \brief Overloaded Object3D method.
|
sl@0
|
244 |
*
|
sl@0
|
245 |
* \param self Appearance object
|
sl@0
|
246 |
* \param time current world time
|
sl@0
|
247 |
* \return minimum validity
|
sl@0
|
248 |
*/
|
sl@0
|
249 |
static M3Gint m3gAppearanceApplyAnimation(Object *self, M3Gint time) {
|
sl@0
|
250 |
M3Gint i, validity, minValidity = 0x7fffffff;
|
sl@0
|
251 |
Appearance *appearance = (Appearance *)self;
|
sl@0
|
252 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
253 |
|
sl@0
|
254 |
if (appearance->compositingMode != NULL) {
|
sl@0
|
255 |
validity = M3G_VFUNC(Object, appearance->compositingMode, applyAnimation)((Object *)appearance->compositingMode, time);
|
sl@0
|
256 |
minValidity = (validity < minValidity ? validity : minValidity);
|
sl@0
|
257 |
}
|
sl@0
|
258 |
if (appearance->fog != NULL) {
|
sl@0
|
259 |
validity = M3G_VFUNC(Object, appearance->fog, applyAnimation)((Object *)appearance->fog, time);
|
sl@0
|
260 |
minValidity = (validity < minValidity ? validity : minValidity);
|
sl@0
|
261 |
}
|
sl@0
|
262 |
if (appearance->material != NULL) {
|
sl@0
|
263 |
validity = M3G_VFUNC(Object, appearance->material, applyAnimation)((Object *)appearance->material, time);
|
sl@0
|
264 |
minValidity = (validity < minValidity ? validity : minValidity);
|
sl@0
|
265 |
}
|
sl@0
|
266 |
for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
|
sl@0
|
267 |
if (appearance->texture[i] != NULL) {
|
sl@0
|
268 |
validity = M3G_VFUNC(Object, appearance->texture[i], applyAnimation)((Object *)appearance->texture[i], time);
|
sl@0
|
269 |
minValidity = (validity < minValidity ? validity : minValidity);
|
sl@0
|
270 |
}
|
sl@0
|
271 |
}
|
sl@0
|
272 |
|
sl@0
|
273 |
/* no animations can target an Appearance directly, so we need
|
sl@0
|
274 |
not call super.applyAnimation() here. */
|
sl@0
|
275 |
return minValidity;
|
sl@0
|
276 |
}
|
sl@0
|
277 |
|
sl@0
|
278 |
/*!
|
sl@0
|
279 |
* \internal
|
sl@0
|
280 |
* \brief Overloaded Object3D method.
|
sl@0
|
281 |
*/
|
sl@0
|
282 |
static Object *m3gAppearanceFindID(Object *self, M3Gint userID)
|
sl@0
|
283 |
{
|
sl@0
|
284 |
int i;
|
sl@0
|
285 |
Appearance *app = (Appearance *)self;
|
sl@0
|
286 |
Object *found = m3gObjectFindID(self, userID);
|
sl@0
|
287 |
|
sl@0
|
288 |
if (!found && app->compositingMode) {
|
sl@0
|
289 |
found = m3gFindID((Object*) app->compositingMode, userID);
|
sl@0
|
290 |
}
|
sl@0
|
291 |
if (!found && app->polygonMode) {
|
sl@0
|
292 |
found = m3gFindID((Object*) app->polygonMode, userID);
|
sl@0
|
293 |
}
|
sl@0
|
294 |
if (!found && app->fog) {
|
sl@0
|
295 |
found = m3gFindID((Object*) app->fog, userID);
|
sl@0
|
296 |
}
|
sl@0
|
297 |
if (!found && app->material) {
|
sl@0
|
298 |
found = m3gFindID((Object*) app->material, userID);
|
sl@0
|
299 |
}
|
sl@0
|
300 |
for (i = 0; !found && i < M3G_NUM_TEXTURE_UNITS; ++i) {
|
sl@0
|
301 |
if (app->texture[i]) {
|
sl@0
|
302 |
found = m3gFindID((Object*) app->texture[i], userID);
|
sl@0
|
303 |
}
|
sl@0
|
304 |
}
|
sl@0
|
305 |
return found;
|
sl@0
|
306 |
}
|
sl@0
|
307 |
|
sl@0
|
308 |
/*!
|
sl@0
|
309 |
* \internal
|
sl@0
|
310 |
* \brief Overloaded Object3D method.
|
sl@0
|
311 |
*
|
sl@0
|
312 |
* \param self Appearance object
|
sl@0
|
313 |
* \param references array of reference objects
|
sl@0
|
314 |
* \return number of references
|
sl@0
|
315 |
*/
|
sl@0
|
316 |
static M3Gint m3gAppearanceDoGetReferences(Object *self, Object **references)
|
sl@0
|
317 |
{
|
sl@0
|
318 |
Appearance *app = (Appearance *)self;
|
sl@0
|
319 |
M3Gint i, num = m3gObjectDoGetReferences(self, references);
|
sl@0
|
320 |
if (app->compositingMode != NULL) {
|
sl@0
|
321 |
if (references != NULL)
|
sl@0
|
322 |
references[num] = (Object *)app->compositingMode;
|
sl@0
|
323 |
num++;
|
sl@0
|
324 |
}
|
sl@0
|
325 |
if (app->polygonMode != NULL) {
|
sl@0
|
326 |
if (references != NULL)
|
sl@0
|
327 |
references[num] = (Object *)app->polygonMode;
|
sl@0
|
328 |
num++;
|
sl@0
|
329 |
}
|
sl@0
|
330 |
if (app->fog != NULL) {
|
sl@0
|
331 |
if (references != NULL)
|
sl@0
|
332 |
references[num] = (Object *)app->fog;
|
sl@0
|
333 |
num++;
|
sl@0
|
334 |
}
|
sl@0
|
335 |
if (app->material != NULL) {
|
sl@0
|
336 |
if (references != NULL)
|
sl@0
|
337 |
references[num] = (Object *)app->material;
|
sl@0
|
338 |
num++;
|
sl@0
|
339 |
}
|
sl@0
|
340 |
for (i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
|
sl@0
|
341 |
if (app->texture[i] != NULL) {
|
sl@0
|
342 |
if (references != NULL)
|
sl@0
|
343 |
references[num] = (Object *)app->texture[i];
|
sl@0
|
344 |
num++;
|
sl@0
|
345 |
}
|
sl@0
|
346 |
}
|
sl@0
|
347 |
return num;
|
sl@0
|
348 |
}
|
sl@0
|
349 |
|
sl@0
|
350 |
|
sl@0
|
351 |
/*!
|
sl@0
|
352 |
* \internal
|
sl@0
|
353 |
* \brief Overloaded Object3D method.
|
sl@0
|
354 |
*
|
sl@0
|
355 |
* \param originalObj original Appearance object
|
sl@0
|
356 |
* \param cloneObj pointer to cloned Appearance object
|
sl@0
|
357 |
* \param pairs array for all object-duplicate pairs
|
sl@0
|
358 |
* \param numPairs number of pairs
|
sl@0
|
359 |
*/
|
sl@0
|
360 |
static M3Gbool m3gAppearanceDuplicate(const Object *originalObj,
|
sl@0
|
361 |
Object **cloneObj,
|
sl@0
|
362 |
Object **pairs,
|
sl@0
|
363 |
M3Gint *numPairs)
|
sl@0
|
364 |
{
|
sl@0
|
365 |
M3Gint i;
|
sl@0
|
366 |
Appearance *original = (Appearance *)originalObj;
|
sl@0
|
367 |
Appearance *clone = (Appearance *)m3gCreateAppearance(originalObj->interface);
|
sl@0
|
368 |
*cloneObj = (Object *)clone;
|
sl@0
|
369 |
if (*cloneObj == NULL) {
|
sl@0
|
370 |
return M3G_FALSE;
|
sl@0
|
371 |
}
|
sl@0
|
372 |
|
sl@0
|
373 |
if (m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
|
sl@0
|
374 |
clone->layer = original->layer;
|
sl@0
|
375 |
|
sl@0
|
376 |
M3G_ASSIGN_REF(clone->compositingMode, original->compositingMode);
|
sl@0
|
377 |
M3G_ASSIGN_REF(clone->fog, original->fog);
|
sl@0
|
378 |
M3G_ASSIGN_REF(clone->polygonMode, original->polygonMode);
|
sl@0
|
379 |
M3G_ASSIGN_REF(clone->material, original->material);
|
sl@0
|
380 |
for (i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
|
sl@0
|
381 |
M3G_ASSIGN_REF(clone->texture[i], original->texture[i]);
|
sl@0
|
382 |
}
|
sl@0
|
383 |
|
sl@0
|
384 |
m3gRegenerateSortKey(clone);
|
sl@0
|
385 |
|
sl@0
|
386 |
return M3G_TRUE;
|
sl@0
|
387 |
}
|
sl@0
|
388 |
else {
|
sl@0
|
389 |
return M3G_FALSE;
|
sl@0
|
390 |
}
|
sl@0
|
391 |
}
|
sl@0
|
392 |
|
sl@0
|
393 |
/*----------------------------------------------------------------------
|
sl@0
|
394 |
* Virtual function table
|
sl@0
|
395 |
*--------------------------------------------------------------------*/
|
sl@0
|
396 |
|
sl@0
|
397 |
static const ObjectVFTable m3gvf_Appearance = {
|
sl@0
|
398 |
m3gAppearanceApplyAnimation,
|
sl@0
|
399 |
m3gObjectIsCompatible,
|
sl@0
|
400 |
m3gObjectUpdateProperty,
|
sl@0
|
401 |
m3gAppearanceDoGetReferences,
|
sl@0
|
402 |
m3gAppearanceFindID,
|
sl@0
|
403 |
m3gAppearanceDuplicate,
|
sl@0
|
404 |
m3gDestroyAppearance
|
sl@0
|
405 |
};
|
sl@0
|
406 |
|
sl@0
|
407 |
|
sl@0
|
408 |
/*----------------------------------------------------------------------
|
sl@0
|
409 |
* Public API functions
|
sl@0
|
410 |
*--------------------------------------------------------------------*/
|
sl@0
|
411 |
|
sl@0
|
412 |
/*!
|
sl@0
|
413 |
* \brief Creates a new Appearance with default values
|
sl@0
|
414 |
*
|
sl@0
|
415 |
* \param hInterface M3G interface
|
sl@0
|
416 |
* \retval Appearance new Appearance object
|
sl@0
|
417 |
* \retval NULL Appearance creating failed
|
sl@0
|
418 |
*/
|
sl@0
|
419 |
/*@access M3GInterface@*/
|
sl@0
|
420 |
/*@access M3GAppearance@*/
|
sl@0
|
421 |
M3G_API M3GAppearance m3gCreateAppearance(M3GInterface hInterface)
|
sl@0
|
422 |
{
|
sl@0
|
423 |
Interface *m3g = (Interface *) hInterface;
|
sl@0
|
424 |
M3G_VALIDATE_INTERFACE(m3g);
|
sl@0
|
425 |
{
|
sl@0
|
426 |
Appearance *appearance = m3gAllocZ(m3g, sizeof(Appearance));
|
sl@0
|
427 |
|
sl@0
|
428 |
if (appearance != NULL) {
|
sl@0
|
429 |
m3gInitObject(&appearance->object, m3g, M3G_CLASS_APPEARANCE);
|
sl@0
|
430 |
m3gRegenerateSortKey(appearance);
|
sl@0
|
431 |
}
|
sl@0
|
432 |
|
sl@0
|
433 |
return (M3GAppearance) appearance;
|
sl@0
|
434 |
}
|
sl@0
|
435 |
}
|
sl@0
|
436 |
|
sl@0
|
437 |
/*!
|
sl@0
|
438 |
* \brief Get compositing mode
|
sl@0
|
439 |
*
|
sl@0
|
440 |
* \param hAppearance Appearance object
|
sl@0
|
441 |
* \return CompositingMode object
|
sl@0
|
442 |
*/
|
sl@0
|
443 |
M3G_API M3GCompositingMode m3gGetCompositingMode(M3GAppearance hAppearance)
|
sl@0
|
444 |
{
|
sl@0
|
445 |
const Appearance *appearance = (const Appearance *) hAppearance;
|
sl@0
|
446 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
447 |
return (M3GCompositingMode)(appearance->compositingMode);
|
sl@0
|
448 |
}
|
sl@0
|
449 |
|
sl@0
|
450 |
/*!
|
sl@0
|
451 |
* \brief Get fog
|
sl@0
|
452 |
*
|
sl@0
|
453 |
* \param hAppearance Appearance object
|
sl@0
|
454 |
* \return Fog object
|
sl@0
|
455 |
*/
|
sl@0
|
456 |
M3G_API M3GFog m3gGetFog(M3GAppearance hAppearance)
|
sl@0
|
457 |
{
|
sl@0
|
458 |
const Appearance *appearance = (const Appearance *) hAppearance;
|
sl@0
|
459 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
460 |
return (M3GFog)(appearance->fog);
|
sl@0
|
461 |
}
|
sl@0
|
462 |
|
sl@0
|
463 |
/*!
|
sl@0
|
464 |
* \brief Get material
|
sl@0
|
465 |
*
|
sl@0
|
466 |
* \param hAppearance Appearance object
|
sl@0
|
467 |
* \return Material object
|
sl@0
|
468 |
*/
|
sl@0
|
469 |
M3G_API M3GMaterial m3gGetMaterial(M3GAppearance hAppearance)
|
sl@0
|
470 |
{
|
sl@0
|
471 |
const Appearance *appearance = (const Appearance *) hAppearance;
|
sl@0
|
472 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
473 |
return (M3GMaterial)(appearance->material);
|
sl@0
|
474 |
}
|
sl@0
|
475 |
|
sl@0
|
476 |
/*!
|
sl@0
|
477 |
* \brief Get polygon mode
|
sl@0
|
478 |
*
|
sl@0
|
479 |
* \param hAppearance Appearance object
|
sl@0
|
480 |
* \return PolygonMode object
|
sl@0
|
481 |
*/
|
sl@0
|
482 |
M3G_API M3GPolygonMode m3gGetPolygonMode(M3GAppearance hAppearance)
|
sl@0
|
483 |
{
|
sl@0
|
484 |
const Appearance *appearance = (const Appearance *) hAppearance;
|
sl@0
|
485 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
486 |
return (M3GPolygonMode)(appearance->polygonMode);
|
sl@0
|
487 |
}
|
sl@0
|
488 |
|
sl@0
|
489 |
/*!
|
sl@0
|
490 |
* \brief Get texture
|
sl@0
|
491 |
*
|
sl@0
|
492 |
* \param hAppearance Appearance object
|
sl@0
|
493 |
* \param unit texturing unit
|
sl@0
|
494 |
* \return Texture2D object
|
sl@0
|
495 |
*/
|
sl@0
|
496 |
M3G_API M3GTexture m3gGetTexture(M3GAppearance hAppearance, M3Gint unit)
|
sl@0
|
497 |
{
|
sl@0
|
498 |
const Appearance *appearance = (const Appearance *) hAppearance;
|
sl@0
|
499 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
500 |
if (!m3gInRange(unit, 0, M3G_NUM_TEXTURE_UNITS - 1)) {
|
sl@0
|
501 |
m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
|
sl@0
|
502 |
return (M3GTexture) NULL;
|
sl@0
|
503 |
}
|
sl@0
|
504 |
return (M3GTexture)(appearance->texture[unit]);
|
sl@0
|
505 |
}
|
sl@0
|
506 |
|
sl@0
|
507 |
/*!
|
sl@0
|
508 |
* \brief Get layer
|
sl@0
|
509 |
*
|
sl@0
|
510 |
* \param hAppearance Appearance object
|
sl@0
|
511 |
* \return layer number
|
sl@0
|
512 |
*/
|
sl@0
|
513 |
M3G_API M3Gint m3gGetLayer(M3GAppearance hAppearance)
|
sl@0
|
514 |
{
|
sl@0
|
515 |
const Appearance *appearance = (const Appearance *) hAppearance;
|
sl@0
|
516 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
517 |
return appearance->layer;
|
sl@0
|
518 |
}
|
sl@0
|
519 |
|
sl@0
|
520 |
/*!
|
sl@0
|
521 |
* \brief Set compositing mode
|
sl@0
|
522 |
*
|
sl@0
|
523 |
* \param hAppearance Appearance object
|
sl@0
|
524 |
* \param hMode CompositingMode object
|
sl@0
|
525 |
*/
|
sl@0
|
526 |
M3G_API void m3gSetCompositingMode(M3GAppearance hAppearance,
|
sl@0
|
527 |
M3GCompositingMode hMode)
|
sl@0
|
528 |
{
|
sl@0
|
529 |
Appearance *appearance = (Appearance *) hAppearance;
|
sl@0
|
530 |
CompositingMode *mode = (CompositingMode *) hMode;
|
sl@0
|
531 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
532 |
|
sl@0
|
533 |
M3G_ASSIGN_REF(appearance->compositingMode, mode);
|
sl@0
|
534 |
|
sl@0
|
535 |
m3gRegenerateSortKey(appearance);
|
sl@0
|
536 |
}
|
sl@0
|
537 |
|
sl@0
|
538 |
/*!
|
sl@0
|
539 |
* \brief Set polygon mode
|
sl@0
|
540 |
*
|
sl@0
|
541 |
* \param hAppearance Appearance object
|
sl@0
|
542 |
* \param hMode PolygonMode object
|
sl@0
|
543 |
*/
|
sl@0
|
544 |
M3G_API void m3gSetPolygonMode(M3GAppearance hAppearance,
|
sl@0
|
545 |
M3GPolygonMode hMode)
|
sl@0
|
546 |
{
|
sl@0
|
547 |
Appearance *appearance = (Appearance *) hAppearance;
|
sl@0
|
548 |
PolygonMode *mode = (PolygonMode *) hMode;
|
sl@0
|
549 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
550 |
|
sl@0
|
551 |
M3G_ASSIGN_REF(appearance->polygonMode, mode);
|
sl@0
|
552 |
|
sl@0
|
553 |
m3gRegenerateSortKey(appearance);
|
sl@0
|
554 |
}
|
sl@0
|
555 |
|
sl@0
|
556 |
/*!
|
sl@0
|
557 |
* \brief Set layer
|
sl@0
|
558 |
*
|
sl@0
|
559 |
* \param hAppearance Appearance object
|
sl@0
|
560 |
* \param layer layer number
|
sl@0
|
561 |
*/
|
sl@0
|
562 |
M3G_API void m3gSetLayer(M3GAppearance hAppearance, M3Gint layer)
|
sl@0
|
563 |
{
|
sl@0
|
564 |
Appearance *appearance = (Appearance *) hAppearance;
|
sl@0
|
565 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
566 |
|
sl@0
|
567 |
/* Check for errors */
|
sl@0
|
568 |
if (!m3gInRange(layer, M3G_APPEARANCE_MIN_LAYER, M3G_APPEARANCE_MAX_LAYER)) {
|
sl@0
|
569 |
m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
|
sl@0
|
570 |
return;
|
sl@0
|
571 |
}
|
sl@0
|
572 |
|
sl@0
|
573 |
appearance->layer = (M3Gshort) layer;
|
sl@0
|
574 |
|
sl@0
|
575 |
m3gRegenerateSortKey(appearance);
|
sl@0
|
576 |
}
|
sl@0
|
577 |
|
sl@0
|
578 |
/*!
|
sl@0
|
579 |
* \brief Set material
|
sl@0
|
580 |
*
|
sl@0
|
581 |
* \param hAppearance Appearance object
|
sl@0
|
582 |
* \param hMaterial Material object
|
sl@0
|
583 |
*/
|
sl@0
|
584 |
M3G_API void m3gSetMaterial(M3GAppearance hAppearance,
|
sl@0
|
585 |
M3GMaterial hMaterial)
|
sl@0
|
586 |
{
|
sl@0
|
587 |
Appearance *appearance = (Appearance *) hAppearance;
|
sl@0
|
588 |
Material *material = (Material *) hMaterial;
|
sl@0
|
589 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
590 |
|
sl@0
|
591 |
M3G_ASSIGN_REF(appearance->material, material);
|
sl@0
|
592 |
|
sl@0
|
593 |
if (material != NULL) {
|
sl@0
|
594 |
appearance->vertexMask |= (M3Gushort)M3G_NORMAL_BIT;
|
sl@0
|
595 |
}
|
sl@0
|
596 |
else {
|
sl@0
|
597 |
appearance->vertexMask &= ~(M3Gushort)M3G_NORMAL_BIT;
|
sl@0
|
598 |
}
|
sl@0
|
599 |
|
sl@0
|
600 |
m3gRegenerateSortKey(appearance);
|
sl@0
|
601 |
}
|
sl@0
|
602 |
|
sl@0
|
603 |
/*!
|
sl@0
|
604 |
* \brief Set texture
|
sl@0
|
605 |
*
|
sl@0
|
606 |
* \param hAppearance Appearance object
|
sl@0
|
607 |
* \param unit texturing unit
|
sl@0
|
608 |
* \param hTexture Texture2D object
|
sl@0
|
609 |
*/
|
sl@0
|
610 |
M3G_API void m3gSetTexture(M3GAppearance hAppearance,
|
sl@0
|
611 |
M3Gint unit, M3GTexture hTexture)
|
sl@0
|
612 |
{
|
sl@0
|
613 |
Appearance *appearance = (Appearance *) hAppearance;
|
sl@0
|
614 |
Texture *texture = (Texture *) hTexture;
|
sl@0
|
615 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
616 |
|
sl@0
|
617 |
if (!m3gInRange(unit, 0, M3G_NUM_TEXTURE_UNITS - 1)) {
|
sl@0
|
618 |
m3gRaiseError(M3G_INTERFACE(appearance), M3G_INVALID_INDEX);
|
sl@0
|
619 |
return;
|
sl@0
|
620 |
}
|
sl@0
|
621 |
|
sl@0
|
622 |
M3G_ASSIGN_REF(appearance->texture[unit], texture);
|
sl@0
|
623 |
|
sl@0
|
624 |
if (texture != NULL) {
|
sl@0
|
625 |
appearance->vertexMask |= (M3Gushort) (M3G_TEXCOORD0_BIT << unit);
|
sl@0
|
626 |
}
|
sl@0
|
627 |
else {
|
sl@0
|
628 |
appearance->vertexMask &= (M3Gushort) ~(M3G_TEXCOORD0_BIT << unit);
|
sl@0
|
629 |
}
|
sl@0
|
630 |
|
sl@0
|
631 |
m3gRegenerateSortKey(appearance);
|
sl@0
|
632 |
}
|
sl@0
|
633 |
|
sl@0
|
634 |
/*!
|
sl@0
|
635 |
* \brief Set fog
|
sl@0
|
636 |
*
|
sl@0
|
637 |
* \param hAppearance Appearance object
|
sl@0
|
638 |
* \param hFog Fog object
|
sl@0
|
639 |
*/
|
sl@0
|
640 |
M3G_API void m3gSetFog(M3GAppearance hAppearance, M3GFog hFog)
|
sl@0
|
641 |
{
|
sl@0
|
642 |
Appearance *appearance = (Appearance *) hAppearance;
|
sl@0
|
643 |
M3G_VALIDATE_OBJECT(appearance);
|
sl@0
|
644 |
|
sl@0
|
645 |
M3G_ASSIGN_REF(appearance->fog, hFog);
|
sl@0
|
646 |
|
sl@0
|
647 |
m3gRegenerateSortKey(appearance);
|
sl@0
|
648 |
}
|
sl@0
|
649 |
|