Update contrib.
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
14 * Description: Vertex buffer implementation
22 * \brief Vertex buffer implementation
25 #ifndef M3G_CORE_INCLUDE
26 # error included by m3g_core.c; do not compile separately.
29 #include "m3g_vertexbuffer.h"
30 #include "m3g_vertexarray.h"
32 #include "m3g_appearance.h"
33 #include "m3g_node.h" /* for NODE_ALPHA_FACTOR_BITS */
35 /*----------------------------------------------------------------------
37 *--------------------------------------------------------------------*/
39 /*----------------------------------------------------------------------
41 *--------------------------------------------------------------------*/
45 * \brief Deletes a vertex buffer
47 * \param obj VertexBuffer object
49 static void m3gDestroyVertexBuffer(Object *obj)
52 VertexBuffer *buffer = (VertexBuffer *) obj;
53 M3G_VALIDATE_OBJECT(buffer);
56 M3G_ASSERT(M3G_FALSE);
57 m3gReleaseVertexBuffer(buffer);
60 M3G_ASSIGN_REF(buffer->vertices, NULL);
61 M3G_ASSIGN_REF(buffer->normals, NULL);
62 M3G_ASSIGN_REF(buffer->colors, NULL);
63 for(i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
64 M3G_ASSIGN_REF(buffer->texCoords[i], NULL);
67 m3gDestroyObject(&buffer->object);
72 * \brief Applies the scale and bias values of a vertex buffer to the
75 * The scale and bias transformations are applied to the existing
76 * values in the GL_MODELVIEW and GL_TEXTURE matrix stacks.
78 * \param buffer VertexBuffer object
80 static void m3gApplyScaleAndBias(const VertexBuffer *buffer)
82 M3G_VALIDATE_OBJECT(buffer);
84 glMatrixMode(GL_TEXTURE);
87 for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
88 if (buffer->texCoords[i] != NULL) {
89 glActiveTexture((GLenum)(GL_TEXTURE0 + i));
90 glTranslatef(buffer->texCoordBias[i][0],
91 buffer->texCoordBias[i][1],
92 buffer->texCoordBias[i][2]);
93 glScalef(buffer->texCoordScale[i],
94 buffer->texCoordScale[i],
95 buffer->texCoordScale[i]);
100 glMatrixMode(GL_MODELVIEW);
101 if (buffer->vertices != NULL) {
102 glTranslatef(buffer->vertexBias[0],
103 buffer->vertexBias[1],
104 buffer->vertexBias[2]);
105 glScalef(buffer->vertexScale,
107 buffer->vertexScale);
113 * \brief Locks a vertex buffer for subsequent rendering
115 * \param buffer VertexBuffer object
116 * \param alphaFactor alpha factor as 1.16 fixed point
118 static void m3gLockVertexBuffer(const VertexBuffer *buffer,
121 M3G_VALIDATE_OBJECT(buffer);
122 M3G_ASSERT(!buffer->locked);
124 if (buffer->colors != NULL) {
125 glEnableClientState(GL_COLOR_ARRAY);
126 m3gLockColorArray(buffer->colors, alphaFactor);
129 GLfixed r = buffer->defaultColor.r;
130 GLfixed g = buffer->defaultColor.g;
131 GLfixed b = buffer->defaultColor.b;
132 GLfixed a = buffer->defaultColor.a * alphaFactor;
134 r = (r << 8) + r + (r >> 7);
135 g = (g << 8) + g + (g >> 7);
136 b = (b << 8) + b + (b >> 7);
137 a = (a >> (NODE_ALPHA_FACTOR_BITS - 8))
138 + (a >> NODE_ALPHA_FACTOR_BITS)
139 + (a >> (NODE_ALPHA_FACTOR_BITS + 7));
141 glDisableClientState(GL_COLOR_ARRAY);
142 glColor4x(r, g, b, a);
145 if (buffer->normals != NULL) {
146 glEnableClientState(GL_NORMAL_ARRAY);
147 m3gLockNormalArray(buffer->normals);
150 glDisableClientState(GL_NORMAL_ARRAY);
153 if (buffer->vertices != NULL) {
154 glEnableClientState(GL_VERTEX_ARRAY);
155 m3gLockVertexArray(buffer->vertices);
158 glDisableClientState(GL_VERTEX_ARRAY);
163 for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
164 const VertexArray *array = buffer->texCoords[i];
165 glClientActiveTexture(GL_TEXTURE0 + i);
166 glActiveTexture(GL_TEXTURE0 + i);
168 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
169 m3gLockTexCoordArray(array);
172 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
177 ((VertexBuffer*)buffer)->locked = M3G_TRUE;
182 * \brief Releases a vertex buffer
184 * \param buffer VertexBuffer object
186 static void m3gReleaseVertexBuffer(const VertexBuffer *buffer)
188 M3G_VALIDATE_OBJECT(buffer);
189 M3G_ASSERT(buffer->locked);
191 if (buffer->colors != NULL) {
192 m3gUnlockArray(buffer->colors);
194 if (buffer->normals != NULL) {
195 m3gUnlockArray(buffer->normals);
197 if (buffer->vertices != NULL) {
198 m3gUnlockArray(buffer->vertices);
202 for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
203 const VertexArray *array = buffer->texCoords[i];
205 m3gUnlockArray(array);
210 ((VertexBuffer*)buffer)->locked = M3G_FALSE;
215 * \brief Gets a vertex position. Scale and bias
218 * \param buffer VertexBuffer object
219 * \param idx index of coordinate
220 * \param v vector to fill in
221 * \retval M3G_TRUE get ok
222 * \retval M3G_FALSE no such vertex
224 static M3Gbool m3gGetVertex(const VertexBuffer *buffer, M3Gint idx, M3GVec3 *v)
226 return m3gGetCoordinates(buffer->vertices, 3, idx, &v->x);
231 * \brief Gets a normal coordinate.
233 * \param buffer VertexBuffer object
234 * \param idx index of coordinate
235 * \param v vector to fill in
236 * \retval M3G_TRUE get ok
237 * \retval M3G_FALSE no such vertex
239 static M3Gbool m3gGetNormal(const VertexBuffer *buffer, M3Gint idx, M3GVec3 *v)
241 return m3gGetCoordinates(buffer->normals, 3, idx, &v->x);
246 * \brief Gets a texture coordinate, used in pick routines.
247 * Scale and bias are applied to the coordinates.
249 * \param buffer VertexBuffer object
250 * \param idx index of coordinate
251 * \param unit texturing unit
252 * \param v vector to fill in
253 * \retval M3G_TRUE get ok
254 * \retval M3G_FALSE no such vertex
256 static M3Gbool m3gGetTexCoord(const VertexBuffer *buffer, M3Gint idx, M3Gint unit, M3GVec3 *v)
259 res = m3gGetCoordinates(buffer->texCoords[unit], 2, idx, &v->x);
261 v->x = m3gMul(v->x, buffer->texCoordScale[unit]);
262 v->y = m3gMul(v->y, buffer->texCoordScale[unit]);
264 v->x = m3gAdd(v->x, buffer->texCoordBias[unit][0]);
265 v->y = m3gAdd(v->y, buffer->texCoordBias[unit][1]);
274 * \brief Gets vertex buffer positions bounding box.
276 * The bounding box is returned as floats, with scale and bias
279 * \param buffer VertexBuffer object
280 * \param boundingBox bounding box float array
282 static void m3gGetBoundingBox(VertexBuffer *vb, AABB *boundingBox)
284 /* If timestamp is changed, refresh bounding box */
286 if (vb->vertices && (m3gGetArrayTimestamp(vb->vertices)
287 != vb->verticesTimestamp)) {
289 vb->verticesTimestamp = m3gGetArrayTimestamp(vb->vertices);
290 m3gGetArrayBoundingBox(vb->vertices, ab);
292 vb->bbox.min[0] = m3gMadd(ab[0], vb->vertexScale, vb->vertexBias[0]);
293 vb->bbox.min[1] = m3gMadd(ab[1], vb->vertexScale, vb->vertexBias[1]);
294 vb->bbox.min[2] = m3gMadd(ab[2], vb->vertexScale, vb->vertexBias[2]);
295 vb->bbox.max[0] = m3gMadd(ab[3], vb->vertexScale, vb->vertexBias[0]);
296 vb->bbox.max[1] = m3gMadd(ab[4], vb->vertexScale, vb->vertexBias[1]);
297 vb->bbox.max[2] = m3gMadd(ab[5], vb->vertexScale, vb->vertexBias[2]);
299 /* Flip the bounding box if the scale was negative */
301 if (vb->vertexScale < 0) {
303 for (i = 0; i < 3; ++i) {
304 M3Gfloat t = vb->bbox.min[i];
305 vb->bbox.min[i] = vb->bbox.max[i];
310 *boundingBox = vb->bbox;
315 * \brief Gets vertex buffer timestamp.
317 * \param buffer VertexBuffer object
320 static M3Gint m3gGetTimestamp(const VertexBuffer *buffer)
322 if (buffer->vertices &&
323 m3gGetArrayTimestamp(buffer->vertices) != buffer->verticesTimestamp) {
324 return buffer->timestamp + 1;
326 return buffer->timestamp;
330 * Updates the vertex count bookkeeping when setting vertex
333 * \param buffer VertexBuffer object
334 * \param oldArray VertexArray object
335 * \param newArray VertexArray object
336 * \param maskBit array mask bit
338 static void m3gUpdateArray(VertexBuffer *buffer,
339 VertexArray *oldArray,
340 VertexArray *newArray,
343 M3Gint change = (oldArray == NULL && newArray != NULL) ? 1 :
344 (oldArray != NULL && newArray == NULL) ? -1 :
347 /* If adding or replacing an array, set the initial vertex count,
348 * or compare the new array against the current vertex count */
350 if (newArray != NULL) {
351 if (buffer->arrayCount == 0 || (buffer->arrayCount == 1
353 buffer->vertexCount = m3gGetArrayVertexCount(newArray);
355 else if (m3gGetArrayVertexCount(newArray) != buffer->vertexCount) {
356 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
361 /* Update the array bitmask */
363 if (newArray != NULL) {
364 buffer->arrayMask |= maskBit;
367 buffer->arrayMask &= ~maskBit;
370 /* Update the array count, and reset the vertex count to zero if
371 * no arrays remain */
373 buffer->arrayCount += change;
374 if (buffer->arrayCount == 0) {
375 M3G_ASSERT(buffer->arrayMask == 0);
376 buffer->vertexCount = 0;
382 * \brief Overloaded Object3D method
384 * \param self VertexBuffer object
385 * \param references array of reference objects
386 * \return number of references
388 static M3Gint m3gVertexBufferDoGetReferences(Object *self, Object **references)
390 VertexBuffer *vb = (VertexBuffer *)self;
391 M3Gint i, num = m3gObjectDoGetReferences(self, references);
392 if (vb->vertices != NULL) {
393 if (references != NULL)
394 references[num] = (Object *)vb->vertices;
397 if (vb->normals != NULL) {
398 if (references != NULL)
399 references[num] = (Object *)vb->normals;
402 if (vb->colors != NULL) {
403 if (references != NULL)
404 references[num] = (Object *)vb->colors;
407 for (i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
408 if (vb->texCoords[i] != NULL) {
409 if (references != NULL)
410 references[num] = (Object *)vb->texCoords[i];
419 * \brief Overloaded Object3D method
421 static Object *m3gVertexBufferFindID(Object *self, M3Gint userID)
424 VertexBuffer *vb = (VertexBuffer *)self;
425 Object *found = m3gObjectFindID(self, userID);
427 if (!found && vb->vertices != NULL) {
428 found = m3gFindID((Object*) vb->vertices, userID);
430 if (!found && vb->normals != NULL) {
431 found = m3gFindID((Object*) vb->normals, userID);
433 if (!found && vb->colors != NULL) {
434 found = m3gFindID((Object*) vb->colors, userID);
436 for (i = 0; !found && i < M3G_NUM_TEXTURE_UNITS; ++i) {
437 if (vb->texCoords[i] != NULL) {
438 found = m3gFindID((Object*) vb->texCoords[i], userID);
446 * \brief Duplicates vertex buffer data and array configuration
448 static void m3gDuplicateVertexBufferData(VertexBuffer *clone,
449 const VertexBuffer *original)
453 clone->vertexScale = original->vertexScale;
454 m3gCopy(clone->vertexBias, original->vertexBias, 3 * sizeof(GLfloat));
455 clone->defaultColor = original->defaultColor;
456 clone->locked = original->locked;
457 clone->vertexCount = original->vertexCount;
458 clone->arrayCount = original->arrayCount;
459 clone->arrayMask = original->arrayMask;
460 clone->timestamp = original->timestamp;
462 for (i = 0; i < M3G_NUM_TEXTURE_UNITS; i++) {
463 clone->texCoordScale[i] = original->texCoordScale[i];
464 clone->texCoordBias[i][0] = original->texCoordBias[i][0];
465 clone->texCoordBias[i][1] = original->texCoordBias[i][1];
466 clone->texCoordBias[i][2] = original->texCoordBias[i][2];
467 M3G_ASSIGN_REF(clone->texCoords[i], original->texCoords[i]);
469 M3G_ASSIGN_REF(clone->colors, original->colors);
470 M3G_ASSIGN_REF(clone->normals, original->normals);
471 M3G_ASSIGN_REF(clone->vertices, original->vertices);
476 * \brief Overloaded Object3D method
478 * \param originalObj original VertexBuffer object
479 * \param cloneObj pointer to cloned VertexBuffer object
480 * \param pairs array for all object-duplicate pairs
481 * \param numPairs number of pairs
483 static M3Gbool m3gVertexBufferDuplicate(const Object *originalObj,
488 VertexBuffer *original = (VertexBuffer*) originalObj;
490 M3G_ASSERT(*cloneObj == NULL); /* no derived classes */
492 /* Create the clone object */
494 clone = (VertexBuffer*) m3gCreateVertexBuffer(originalObj->interface);
498 *cloneObj = (Object *)clone;
500 /* Duplicate base class data */
502 if (!m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
506 /* Duplicate our own data */
508 m3gDuplicateVertexBufferData(clone, original);
514 * \brief Overloaded Object3D method.
516 * \param property animation property
517 * \retval M3G_TRUE property supported
518 * \retval M3G_FALSE property not supported
520 static M3Gbool m3gVertexBufferIsCompatible(M3Gint property)
527 return m3gObjectIsCompatible(property);
533 * \brief Overloaded Object3D method
535 * \param self VertexBuffer object
536 * \param property animation property
537 * \param valueSize size of value array
538 * \param value value array
540 static void m3gVertexBufferUpdateProperty(Object *self,
543 const M3Gfloat *value)
545 VertexBuffer *buffer = (VertexBuffer *) self;
546 M3G_VALIDATE_OBJECT(buffer);
547 M3G_ASSERT_PTR(value);
551 M3G_ASSERT(valueSize >= 1);
552 buffer->defaultColor.a =
553 (GLubyte)m3gAdd(m3gMul(255.f, m3gClampFloat(value[0], 0.f, 1.f)), 0.5f);
556 M3G_ASSERT(valueSize >= 3);
557 buffer->defaultColor.r =
558 (GLubyte)m3gAdd(m3gMul(255.f, m3gClampFloat(value[0], 0.f, 1.f)), 0.5f);
559 buffer->defaultColor.g =
560 (GLubyte)m3gAdd(m3gMul(255.f, m3gClampFloat(value[1], 0.f, 1.f)), 0.5f);
561 buffer->defaultColor.b =
562 (GLubyte)m3gAdd(m3gMul(255.f, m3gClampFloat(value[2], 0.f, 1.f)), 0.5f);
565 m3gObjectUpdateProperty(self, property, valueSize, value);
571 * \brief Checks that a vertex buffer can be properly rendered
573 * The vertex format required by \c app is compared against the vertex
574 * arrays included in \c vb, and \c vb is checked to have at least \c
575 * maxIndex vertex entries.
577 * \param vb VertexBuffer object
578 * \param app Appearance object
579 * \param maxIndex maximum index in index buffer
580 * \retval M3G_TRUE valid state
581 * \retval M3G_FALSE invalid state
583 static M3Gbool m3gValidateVertexBuffer(const VertexBuffer *vb,
584 const Appearance *app,
589 reqMask = M3G_POSITION_BIT;
590 if ((m3gGetArrayMask(vb) & reqMask) != reqMask) {
593 return (m3gGetNumVertices(vb) > maxIndex);
598 * \brief Sets a vertex buffer up for subsequent vertex modification
600 * A specified subset of the arrays of \c srcBuffer will be replicated
601 * in \c buffer, without copying the contents. The others will be
602 * copied as references only.
604 * \param buffer the modified buffer
605 * \param srcBuffer the source buffer
606 * \param arrayMask bitmask of arrays to modify
607 * \param createArrays M3G_TRUE to create the arrays specified by
608 * \c arrayMask, M3G_FALSE to leave them NULL
609 * \retval M3G_TRUE success
610 * \retval M3G_FALSE out of memory
612 static M3Gbool m3gMakeModifiedVertexBuffer(VertexBuffer *buffer,
613 const VertexBuffer *srcBuffer,
614 M3Gbitmask arrayMask,
615 M3Gbool createArrays)
617 M3G_VALIDATE_OBJECT(buffer);
618 M3G_VALIDATE_OBJECT(srcBuffer);
620 Interface *m3g = M3G_INTERFACE(buffer);
624 /* First, just copy the data from the other buffer */
626 m3gDuplicateVertexBufferData(buffer, srcBuffer);
628 /* Now, override the specified arrays: release the existing
629 * array, and either allocate a new one or leave as NULL,
630 * depending on the value of the createArrays flag */
632 # define MODIFY_ARRAY(bit, name) \
633 if (arrayMask & (bit)) { \
635 if (srcBuffer->name && createArrays) { \
636 array = m3gCreateVertexArray( \
638 srcBuffer->name->vertexCount, \
639 srcBuffer->name->elementSize, \
640 srcBuffer->name->elementType == GL_SHORT ? M3G_SHORT : M3G_BYTE); \
645 m3gUpdateArray(buffer, buffer->name, array, bit); \
646 M3G_ASSIGN_REF(buffer->name, array); \
649 MODIFY_ARRAY(M3G_POSITION_BIT, vertices);
650 MODIFY_ARRAY(M3G_COLOR_BIT, colors);
651 MODIFY_ARRAY(M3G_NORMAL_BIT, normals);
653 for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
654 MODIFY_ARRAY(M3G_TEXCOORD0_BIT << i, texCoords[i]);
663 /*----------------------------------------------------------------------
664 * Virtual function table
665 *--------------------------------------------------------------------*/
667 static const ObjectVFTable m3gvf_VertexBuffer = {
668 m3gObjectApplyAnimation,
669 m3gVertexBufferIsCompatible,
670 m3gVertexBufferUpdateProperty,
671 m3gVertexBufferDoGetReferences,
672 m3gVertexBufferFindID,
673 m3gVertexBufferDuplicate,
674 m3gDestroyVertexBuffer
678 /*----------------------------------------------------------------------
679 * Public API functions
680 *--------------------------------------------------------------------*/
683 * \brief Creates an empty vertex buffer
685 * \param interface M3G interface
686 * \retval VertexBuffer new VertexBuffer object
687 * \retval NULL VertexBuffer creating failed
689 /*@access M3Ginterface@*/
690 /*@access M3Gobject@*/
691 M3G_API M3GVertexBuffer m3gCreateVertexBuffer(M3GInterface interface)
693 Interface *m3g = (Interface *) interface;
694 M3G_VALIDATE_INTERFACE(m3g);
697 VertexBuffer *buffer = m3gAllocZ(m3g, sizeof(VertexBuffer));
699 if (buffer != NULL) {
700 m3gInitObject(&buffer->object, m3g, M3G_CLASS_VERTEX_BUFFER);
702 /* Set default color to white */
703 buffer->defaultColor.r = (GLubyte) 0xFF;
704 buffer->defaultColor.g = (GLubyte) 0xFF;
705 buffer->defaultColor.b = (GLubyte) 0xFF;
706 buffer->defaultColor.a = (GLubyte) 0xFF;
709 return (M3GVertexBuffer) buffer;
714 * \brief Sets the color array of a vertex buffer
716 * \param hBuffer VertexBuffer object
717 * \param hArray VertexArray object
719 /*@access M3Gobject@*/
720 M3G_API void m3gSetColorArray(M3GVertexBuffer hBuffer, M3GVertexArray hArray)
722 VertexBuffer *buffer = (VertexBuffer *) hBuffer;
723 VertexArray *array = (VertexArray *) hArray;
724 M3G_VALIDATE_OBJECT(buffer);
727 M3G_VALIDATE_OBJECT(array);
729 /* Check for errors */
730 if (!m3gInRange(array->elementSize, 3, 4) ||
731 array->elementType != M3G_GLTYPE(M3G_BYTE)) {
732 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_VALUE);
737 m3gUpdateArray(buffer, buffer->colors, array, M3G_COLOR_BIT);
738 M3G_ASSIGN_REF(buffer->colors, array);
743 * \brief Sets the normal array of a vertex buffer
745 * \param hBuffer VertexBuffer object
746 * \param hArray VertexArray object
748 /*@access M3Gobject@*/
749 M3G_API void m3gSetNormalArray(M3GVertexBuffer hBuffer, M3GVertexArray hArray)
751 VertexBuffer *buffer = (VertexBuffer *) hBuffer;
752 VertexArray *array = (VertexArray *) hArray;
753 M3G_VALIDATE_OBJECT(buffer);
755 M3G_VALIDATE_OBJECT(array);
757 /* Check for errors */
758 if (array->elementSize != 3) {
759 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_VALUE);
764 m3gUpdateArray(buffer, buffer->normals, array, M3G_NORMAL_BIT);
765 M3G_ASSIGN_REF(buffer->normals, array);
770 * \brief Sets the texture coordinate array of a vertex buffer
772 * \param hBuffer VertexBuffer object
773 * \param unit texturing unit
774 * \param hArray VertexArray object
776 * \param bias bias array
777 * \param biasLength bias array length
779 /*@access M3Gobject@*/
780 M3G_API void m3gSetTexCoordArray(M3GVertexBuffer hBuffer,
782 M3GVertexArray hArray,
783 M3Gfloat scale, M3Gfloat *bias,
786 VertexBuffer *buffer = (VertexBuffer *) hBuffer;
787 VertexArray *array = (VertexArray *) hArray;
789 M3G_VALIDATE_OBJECT(buffer);
791 M3G_VALIDATE_OBJECT(array);
796 if (unit < 0 || unit >= M3G_NUM_TEXTURE_UNITS) {
797 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_INDEX);
802 if (array->elementSize != 2 && array->elementSize != 3) {
803 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
806 if (bias != NULL && biasLength < array->elementSize) {
807 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
812 m3gUpdateArray(buffer, buffer->texCoords[unit], array, M3G_TEXCOORD0_BIT << unit);
813 M3G_ASSIGN_REF(buffer->texCoords[unit], array);
815 if (array != NULL && bias != NULL) {
816 buffer->texCoordBias[unit][0] = bias[0];
817 buffer->texCoordBias[unit][1] = bias[1];
818 if (biasLength > 2) {
819 buffer->texCoordBias[unit][2] = bias[2];
823 buffer->texCoordBias[unit][0] = 0.f;
824 buffer->texCoordBias[unit][1] = 0.f;
825 buffer->texCoordBias[unit][2] = 0.f;
828 buffer->texCoordScale[unit] = scale;
834 * \brief Sets the vertex array of a vertex buffer
836 * \param hBuffer VertexBuffer object
837 * \param hArray VertexArray object
839 * \param bias bias array
840 * \param biasLength bias array length
842 /*@access M3Gobject@*/
843 M3G_API void m3gSetVertexArray(M3GVertexBuffer hBuffer,
844 M3GVertexArray hArray,
846 M3Gfloat *bias, M3Gint biasLength)
848 VertexBuffer *buffer = (VertexBuffer *) hBuffer;
849 VertexArray *array = (VertexArray *) hArray;
850 M3G_VALIDATE_OBJECT(buffer);
852 M3G_VALIDATE_OBJECT(array);
855 if (array != NULL && array->elementSize != 3) {
856 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
860 if (array != NULL && bias != NULL && biasLength < 3) {
861 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
865 m3gUpdateArray(buffer, buffer->vertices, array, M3G_POSITION_BIT);
866 M3G_ASSIGN_REF(buffer->vertices, array);
868 if (array != NULL && bias != NULL) {
869 buffer->vertexBias[0] = bias[0];
870 buffer->vertexBias[1] = bias[1];
871 buffer->vertexBias[2] = bias[2];
874 buffer->vertexBias[0] = 0.f;
875 buffer->vertexBias[1] = 0.f;
876 buffer->vertexBias[2] = 0.f;
878 buffer->vertexScale = scale;
880 /* Make sure we invalidate the cached bounding box */
884 buffer->verticesTimestamp = ~m3gGetArrayTimestamp(array); /*lint !e502 ok for signed */
889 * \brief Sets the default color of a vertex buffer
891 * \param handle VertexBuffer object
892 * \param ARGB default color as ARGB
894 /*@access M3Gobject@*/
896 M3G_API void m3gSetVertexDefaultColor(M3GVertexBuffer handle, M3Guint ARGB)
898 VertexBuffer *buffer = (VertexBuffer *) handle;
899 M3G_VALIDATE_OBJECT(buffer);
901 buffer->defaultColor.b = (GLubyte)(ARGB);
902 buffer->defaultColor.g = (GLubyte)(ARGB >> 8);
903 buffer->defaultColor.r = (GLubyte)(ARGB >> 16);
904 buffer->defaultColor.a = (GLubyte)(ARGB >> 24);
909 * \brief Gets the default color of a vertex buffer
910 * \param handle VertexBuffer object
911 * \return default color as ARGB
913 /*@access M3Gobject@*/
915 M3G_API M3Guint m3gGetVertexDefaultColor(M3GVertexBuffer handle)
918 VertexBuffer *buffer = (VertexBuffer *) handle;
919 M3G_VALIDATE_OBJECT(buffer);
921 ARGB = buffer->defaultColor.a;
923 ARGB |= buffer->defaultColor.r;
925 ARGB |= buffer->defaultColor.g;
927 ARGB |= buffer->defaultColor.b;
933 * \brief Gets vertex array of a vertex buffer
935 * \param handle VertexBuffer object
936 * \param which which array to get
937 * \arg M3G_GET_POSITIONS
938 * \arg M3G_GET_NORMALS
939 * \arg M3G_GET_COLORS
940 * \arg M3G_GET_TEXCOORDS0
941 * \arg M3G_GET_TEXCOORDS0 + 1
942 * \param scaleBias array for scale and bias (s, bx, by, bz)
943 * \param sbLength length of scale bias array
946 /*@access M3Gobject@*/
947 M3G_API M3GVertexArray m3gGetVertexArray(M3GVertexBuffer handle,
949 M3Gfloat *scaleBias, M3Gint sbLength)
952 VertexBuffer *buffer = (VertexBuffer *) handle;
953 M3G_VALIDATE_OBJECT(buffer);
956 case M3G_GET_POSITIONS:
957 if (scaleBias != NULL && sbLength < 4) {
958 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
962 if (scaleBias != NULL) {
963 scaleBias[0] = buffer->vertexScale;
964 scaleBias[1] = buffer->vertexBias[0];
965 scaleBias[2] = buffer->vertexBias[1];
966 scaleBias[3] = buffer->vertexBias[2];
968 return buffer->vertices;
969 case M3G_GET_NORMALS: return buffer->normals;
970 case M3G_GET_COLORS: return buffer->colors;
971 case M3G_GET_TEXCOORDS0:
974 case M3G_GET_TEXCOORDS0 + 1:
975 if (buffer->texCoords[tci] != NULL) {
976 if (scaleBias != NULL && sbLength < (buffer->texCoords[tci]->elementSize + 1)) {
977 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
981 if (scaleBias != NULL) {
982 scaleBias[0] = buffer->texCoordScale[tci];
983 scaleBias[1] = buffer->texCoordBias[tci][0];
984 scaleBias[2] = buffer->texCoordBias[tci][1];
985 if (buffer->texCoords[tci]->elementSize > 2) {
986 scaleBias[3] = buffer->texCoordBias[tci][2];
990 return buffer->texCoords[tci];
992 m3gRaiseError(M3G_INTERFACE(buffer), M3G_INVALID_VALUE);
996 return 0; /* Error */
1000 * \brief Gets vertex count of a vertex buffer
1002 * \param handle VertexBuffer object
1003 * \return vertex count
1006 /*@access M3Gobject@*/
1007 M3G_API M3Gint m3gGetVertexCount(M3GVertexBuffer handle)
1009 VertexBuffer *buffer = (VertexBuffer *) handle;
1010 M3G_VALIDATE_OBJECT(buffer);
1012 return buffer->vertexCount;