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: VertexArray implementation
22 * \brief VertexArray implementation
26 #ifndef M3G_CORE_INCLUDE
27 # error included by m3g_core.c; do not compile separately.
30 #include "m3g_vertexarray.h"
32 #define DIRTY_ALPHA_FACTOR (-1)
34 /*----------------------------------------------------------------------
36 *--------------------------------------------------------------------*/
40 * \brief Signals that the contents of an array have changed
42 static M3G_INLINE void m3gInvalidateArray(VertexArray *array)
44 array->cachedAlphaFactor = DIRTY_ALPHA_FACTOR;
51 /*----------------------------------------------------------------------
53 *--------------------------------------------------------------------*/
57 * \brief Destroys this VertexArray object.
59 * \param obj VertexArray object
61 static void m3gDestroyVertexArray(Object *obj)
63 VertexArray *array = (VertexArray *) obj;
64 M3G_VALIDATE_OBJECT(array);
65 M3G_ASSERT(array->numLocks == 0);
67 Interface *m3g = M3G_INTERFACE(array);
68 m3gFreeObject(m3g, array->data);
69 m3gFreeObject(m3g, array->cachedColors);
71 m3gDestroyObject(&array->object);
76 * \brief Sends color array to OpenGL.
78 * \note Alpha scaling currently prevents an array from being used for
79 * anything else while it is being bound as a color array.
81 * \param array VertexArray object
82 * \param alphaFactor 1.16 alpha factor in [0, 0x10000]
84 static void m3gLockColorArray(const VertexArray *array, M3Gint alphaFactor)
86 Interface *m3g = M3G_INTERFACE(array);
87 M3G_VALIDATE_OBJECT(array);
88 M3G_ASSERT(!array->mapCount);
89 M3G_ASSERT(array->numLocks == 0);
90 M3G_ASSERT(m3gInRange(alphaFactor, 0, 0x10000));
92 /* With an alpha factor of 1.0, we can just load up the original data */
94 if (alphaFactor >= 0x10000) {
95 GLenum type = array->elementType;
96 if (type >= GL_BYTE && type <= GL_UNSIGNED_SHORT) {
97 type |= 0x01; /* force type to unsigned for GL */
99 glColorPointer(type == GL_UNSIGNED_BYTE ? 4 : array->elementSize,
102 m3gMapObject(m3g, array->data));
106 /* With a non-unit alpha factor, we may need to update the
107 * cached pre-scaled colors. */
109 M3Gubyte* const cache = (M3Gubyte *)
110 m3gMapObject(m3g, array->cachedColors);
112 if (array->cachedAlphaFactor != alphaFactor) {
113 M3Gubyte *dst = cache;
116 M3G_VALIDATE_MEMBLOCK(cache);
118 /* Scale the colors, converting from the source format */
120 n = array->vertexCount;
122 /* Byte colors are always padded to 4 bytes per entry,
123 * with the implicit alpha set to 0xFF for RGB colors, so
124 * we can do a near-straight copy. */
126 switch (array->elementType) {
128 case GL_UNSIGNED_BYTE:
130 const M3Gubyte *src = (M3Gubyte *)m3gMapObject(m3g,
132 for (i = 0; i < n; ++i) {
137 M3Guint tmp = *src++ * (M3Guint) alphaFactor;
138 *dst++ = (M3Gubyte)(tmp >> 16);
141 m3gUnmapObject(m3g, array->data);
145 M3G_ASSERT(M3G_FALSE);
148 ((VertexArray*)array)->cachedAlphaFactor = alphaFactor;
151 /* We now have the scaled colors in the cache, so just set the
154 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cache);
158 ++((VertexArray*)array)->numLocks;
163 * \brief Creates the color cache required for alpha factors
165 static M3Gbool m3gCreateAlphaColorCache(VertexArray *array)
167 M3G_VALIDATE_OBJECT(array);
168 M3G_ASSERT(array->cachedColors == 0);
170 /* There are always four bytes per color entry */
172 array->cachedColors = m3gAllocObject(M3G_INTERFACE(array),
173 4 * array->vertexCount);
175 return (array->cachedColors != 0);
180 * \brief Sends normal array to OpenGL.
182 * \param array VertexArray object
184 static void m3gLockNormalArray(const VertexArray *array)
186 M3G_VALIDATE_OBJECT(array);
187 M3G_ASSERT(!array->mapCount);
189 glNormalPointer(array->elementType, array->stride,
190 m3gMapObject(M3G_INTERFACE(array), array->data));
193 ++((VertexArray*)array)->numLocks;
198 * \brief Sends texture coordinate array to OpenGL.
200 * \param array VertexArray object
202 static void m3gLockTexCoordArray(const VertexArray *array)
204 M3G_VALIDATE_OBJECT(array);
205 M3G_ASSERT(!array->mapCount);
207 glTexCoordPointer(array->elementSize,
210 m3gMapObject(M3G_INTERFACE(array), array->data));
213 ++((VertexArray*)array)->numLocks;
218 * \brief Sends vertex array to OpenGL.
220 * \param array VertexArray object
222 static void m3gLockVertexArray(const VertexArray *array)
224 M3G_VALIDATE_OBJECT(array);
225 M3G_ASSERT(!array->mapCount);
227 glVertexPointer(array->elementSize,
230 m3gMapObject(M3G_INTERFACE(array), array->data));
233 ++((VertexArray*)array)->numLocks;
238 * \brief Decreases array lock count.
240 * \param array VertexArray object
242 static void m3gUnlockArray(const VertexArray *array)
244 M3G_VALIDATE_OBJECT(array);
245 M3G_ASSERT(array->numLocks > 0);
247 m3gUnmapObject(M3G_INTERFACE(array), array->data);
249 --((VertexArray*)array)->numLocks;
254 * \brief Clones a VertexArray.
256 * Used by MorphingMesh.
258 * \param array VertexArray object
259 * \return cloned VertexArray object
262 static VertexArray *m3gCloneVertexArray(const VertexArray *array)
265 Interface *m3g = M3G_INTERFACE(array);
267 M3G_VALIDATE_OBJECT(array);
268 M3G_ASSERT(!array->mapCount);
270 clone = (VertexArray *) m3gAlloc(m3g, sizeof(VertexArray));
275 m3gCopy(clone, array, sizeof(VertexArray));
276 m3gInitObject((Object*) clone, m3g, M3G_CLASS_VERTEX_ARRAY);
278 clone->data = m3gAllocObject(m3g, array->vertexCount * array->stride);
281 m3gDestroyObject((Object*) clone);
286 m3gCopy(m3gMapObject(m3g, clone->data),
287 m3gMapObject(m3g, array->data),
288 array->vertexCount * array->stride);
289 m3gUnmapObject(m3g, clone->data);
290 m3gUnmapObject(m3g, array->data);
297 * \brief Gets array vertex count.
299 * \param array VertexArray object
300 * \return number of vertices
302 static M3Gint m3gGetArrayVertexCount(const VertexArray *array)
304 return array->vertexCount;
309 * \brief Returns the minimum and maximum value stored in the array
311 static void m3gGetArrayValueRange(const VertexArray *array,
312 M3Gint *minValue, M3Gint *maxValue)
314 Interface *m3g = M3G_INTERFACE(array);
316 if (array->rangeMin > array->rangeMax) {
317 M3Gint count = array->elementSize * array->vertexCount;
318 M3Gint minVal = 0, maxVal = 0;
321 switch (array->elementType) {
324 const GLbyte *src = (const GLbyte*) m3gMapObject(m3g,
326 const M3Gint c = array->elementSize;
327 const M3Gint skip = array->stride - c;
328 minVal = maxVal = (M3Gint) *src++;
331 for (i = 0; i < c; ++i) {
332 M3Gint v = (M3Gint) *src++;
333 minVal = M3G_MIN(minVal, v);
334 maxVal = M3G_MAX(maxVal, v);
341 case GL_UNSIGNED_BYTE:
343 const GLubyte *src = (const GLubyte*) m3gMapObject(m3g,
345 const M3Gint c = array->elementSize;
346 const M3Gint skip = array->stride - c;
347 minVal = maxVal = (M3Gint) *src++;
350 for (i = 0; i < c; ++i) {
351 M3Gint v = (M3Gint) *src++;
352 minVal = M3G_MIN(minVal, v);
353 maxVal = M3G_MAX(maxVal, v);
362 const GLshort *src = (const GLshort*)
363 m3gMapObject(m3g, array->data);
364 minVal = maxVal = (M3Gint) *src++;
366 M3Gint v = (M3Gint) *src++;
367 minVal = M3G_MIN(minVal, v);
368 maxVal = M3G_MAX(maxVal, v);
372 case GL_UNSIGNED_SHORT:
374 const GLushort *src = (const GLushort*)
375 m3gMapObject(m3g, array->data);
376 minVal = maxVal = (M3Gint) *src++;
378 M3Gint v = (M3Gint) *src++;
379 minVal = M3G_MIN(minVal, v);
380 maxVal = M3G_MAX(maxVal, v);
385 M3G_ASSERT(M3G_FALSE);
388 m3gUnmapObject(m3g, array->data);
390 M3G_ASSERT(m3gInRange(minVal, -32768, 32767));
391 M3G_ASSERT(m3gInRange(maxVal, -32768, 32767));
393 ((VertexArray*)array)->rangeMin = (M3Gshort) minVal;
394 ((VertexArray*)array)->rangeMax = (M3Gshort) maxVal;
397 *minValue = array->rangeMin;
398 *maxValue = array->rangeMax;
403 * \brief Compares attributes of two vertex arrays.
405 * \param array VertexArray object
406 * \param other VertexArray object
407 * \retval M3G_TRUE arrays are compatible
408 * \retval M3G_FALSE arrays are not compatible
410 static M3Gbool m3gIsCompatible(const VertexArray *array, const VertexArray *other)
412 return( other != NULL &&
413 other->elementType == array->elementType &&
414 other->elementSize == array->elementSize &&
415 other->vertexCount == array->vertexCount);
420 * \brief Overloaded Object3D method.
422 * \param originalObj original VertexArray object
423 * \param cloneObj pointer to cloned VertexArray object
424 * \param pairs array for all object-duplicate pairs
425 * \param numPairs number of pairs
427 static M3Gbool m3gVertexArrayDuplicate(const Object *originalObj,
432 VertexArray *clone = m3gCloneVertexArray((VertexArray *)originalObj);
436 *cloneObj = (Object*) clone;
437 return m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs);
442 * \brief Gets array timestamp.
444 * \param array VertexArray object
447 static M3Gint m3gGetArrayTimestamp(const VertexArray *array)
449 return array->timestamp;
454 * \brief Gets array bounding box as shorts.
456 * \param array VertexArray object
457 * \param boundingBox array to fill in
465 static void m3gGetArrayBoundingBox(const VertexArray *array, M3Gshort *boundingBox)
467 Interface *m3g = M3G_INTERFACE(array);
469 M3Gshort minX, minY, minZ;
470 M3Gshort maxX, maxY, maxZ;
474 /* Only support 3 component arrays */
475 if (array->elementSize != 3 || array->vertexCount == 0) {
479 switch(array->elementType) {
480 case M3G_GLTYPE(M3G_BYTE):
481 case M3G_GLTYPE(M3G_UBYTE):
482 bptr = (M3Gbyte *) m3gMapObject(m3g, array->data);
484 minX = maxX = bptr[0];
485 minY = maxY = bptr[1];
486 minZ = maxZ = bptr[2];
489 for (i = 0; i < array->vertexCount - 1; i++) {
490 if (bptr[0] < minX) minX = bptr[0];
491 if (bptr[0] > maxX) maxX = bptr[0];
492 if (bptr[1] < minY) minY = bptr[1];
493 if (bptr[1] > maxY) maxY = bptr[1];
494 if (bptr[2] < minZ) minZ = bptr[2];
495 if (bptr[2] > maxZ) maxZ = bptr[2];
500 case M3G_GLTYPE(M3G_SHORT):
501 case M3G_GLTYPE(M3G_USHORT):
502 sptr = (M3Gshort *) m3gMapObject(m3g, array->data);
504 minX = maxX = sptr[0];
505 minY = maxY = sptr[1];
506 minZ = maxZ = sptr[2];
509 for (i = 0; i < array->vertexCount - 1; i++) {
510 if (sptr[0] < minX) minX = sptr[0];
511 if (sptr[0] > maxX) maxX = sptr[0];
512 if (sptr[1] < minY) minY = sptr[1];
513 if (sptr[1] > maxY) maxY = sptr[1];
514 if (sptr[2] < minZ) minZ = sptr[2];
515 if (sptr[2] > maxZ) maxZ = sptr[2];
525 m3gUnmapObject(m3g, array->data);
527 boundingBox[0] = minX;
528 boundingBox[1] = minY;
529 boundingBox[2] = minZ;
530 boundingBox[3] = maxX;
531 boundingBox[4] = maxY;
532 boundingBox[5] = maxZ;
537 * \brief Gets a coordinate from vertex array.
539 * \param va VertexArray object
540 * \param elementCount elemens in coordinate
541 * \param idx index of coordinate
542 * \param v vector to fill in
543 * \retval M3G_TRUE get ok
544 * \retval M3G_FALSE no such vertex
546 static M3Gbool m3gGetCoordinates(VertexArray *va,
560 m3g = M3G_INTERFACE(va);
562 switch (va->elementType) {
563 case M3G_GLTYPE(M3G_BYTE):
564 case M3G_GLTYPE(M3G_UBYTE):
566 bptr = (M3Gbyte *) m3gMapObject(m3g, va->data);
568 for (i = 0; i < elementCount; ++i) {
573 case M3G_GLTYPE(M3G_SHORT):
574 case M3G_GLTYPE(M3G_USHORT):
576 sptr = (M3Gshort *) m3gMapObject(m3g, va->data);
578 for (i = 0; i < elementCount; ++i) {
584 m3gUnmapObject(m3g, va->data);
588 /*----------------------------------------------------------------------
589 * Virtual function table
590 *--------------------------------------------------------------------*/
592 static const ObjectVFTable m3gvf_VertexArray = {
593 m3gObjectApplyAnimation,
594 m3gObjectIsCompatible,
595 m3gObjectUpdateProperty,
596 m3gObjectDoGetReferences,
598 m3gVertexArrayDuplicate,
599 m3gDestroyVertexArray
603 /*----------------------------------------------------------------------
604 * Public API functions
605 *--------------------------------------------------------------------*/
608 * \brief Creates a VertexArray object.
610 * \param interface M3G interface
611 * \param count Count of vertices
612 * \param size Size of each element [2, 4]
613 * \param type Type of elements
614 * \retval VertexArray new VertexArray object
615 * \retval NULL VertexArray creating failed
618 /*@access M3Ginterface@*/
619 /*@access M3GVertexArray@*/
620 M3G_API M3GVertexArray m3gCreateVertexArray(M3GInterface interface,
625 Interface *m3g = (Interface *) interface;
626 M3G_VALIDATE_INTERFACE(m3g);
629 if (count < 1 || count > 65535 ||
630 size < 2 || size > 4 ||
631 (type != M3G_BYTE && type != M3G_SHORT)) {
632 m3gRaiseError(m3g, M3G_INVALID_VALUE);
637 /* Allocate the array object and its data buffer */
639 VertexArray *array = m3gAllocZ(m3g, (M3Gsizei) sizeof(VertexArray));
646 /* always padded to 4 bytes */
650 array->stride = size * sizeof(M3Gshort);
654 /* Alloc and initialize all values to zero */
655 array->data = m3gAllocObject(m3g, count * array->stride);
661 void *ptr = m3gMapObject(m3g, array->data);
662 m3gZero(ptr, count * array->stride);
663 m3gUnmapObject(m3g, array->data);
666 m3gInitObject(&array->object, m3g, M3G_CLASS_VERTEX_ARRAY);
668 array->elementType = M3G_GLTYPE(type);
669 array->elementSize = size;
670 array->vertexCount = count;
671 m3gInvalidateArray(array);
673 return (M3GVertexArray) array;
678 * \brief Returns the data layout parameters for a vertex array
680 * This gives the format of the data mapped to user memory with \c
683 * \param handle array handle
684 * \param count pointer for number of vertices (output)
685 * \param size pointer for components per vertex (output)
686 * \param type pointer to data element type (output)
687 * \param stride pointer to stride, i.e. number of bytes from
688 * the beginning of one vertex to the next (output)
690 M3G_API void m3gGetVertexArrayParams(M3GVertexArray handle,
696 VertexArray *array = (VertexArray *) handle;
697 M3G_VALIDATE_OBJECT(array);
700 *count = array->vertexCount;
703 *size = array->elementSize;
706 *type = (M3Gdatatype) M3G_M3GTYPE(array->elementType);
709 *stride = array->stride;
714 * \brief Maps the data of a vertex array to application memory
716 * The contents of the array will remain mapped to application memory
717 * until a matching \c m3gUnMapVertexArray call. While mapped to user
718 * memory, the array can not be used for rendering.
720 * Deleting a mapped array will also implicitly unmap it.
722 * \param handle handle of the array to map
723 * \return pointer to the array data
725 M3G_API void *m3gMapVertexArray(M3GVertexArray handle)
727 void *ptr = (void*) m3gMapVertexArrayReadOnly(handle);
729 m3gInvalidateArray((VertexArray*) handle);
735 * \brief Maps a vertex array for reading only
737 * This is the same as m3gMapVertexArray, but maps the array for
738 * reading only, allowing internal optimizations.
741 M3G_API const void *m3gMapVertexArrayReadOnly(M3GVertexArray handle)
743 VertexArray *array = (VertexArray *) handle;
744 M3G_VALIDATE_OBJECT(array);
746 if (array->numLocks > 0) {
747 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_OPERATION);
752 return m3gMapObject(M3G_INTERFACE(array), array->data);
756 * \brief Releases an array mapped to user memory
758 * The pointer obtained with a preceding \c m3gMapVertexArray call
759 * will not be valid after unmapping the array.
761 * \param handle handle of the array to release
763 M3G_API void m3gUnmapVertexArray(M3GVertexArray handle)
765 VertexArray *array = (VertexArray *) handle;
766 M3G_VALIDATE_OBJECT(array);
767 M3G_ASSERT(array->mapCount);
769 m3gUnmapObject(M3G_INTERFACE(array), array->data);
774 * \brief Set a range of vertex array elements
776 * \param handle array handle
777 * \param first index of first vertex to set
778 * \param count number of total vertices to set
779 * \param srcLength length of source data
780 * \param type data type of source data
781 * \param src source data
783 M3G_API void m3gSetVertexArrayElements(M3GVertexArray handle,
784 M3Gint first, M3Gsizei count,
789 VertexArray *array = (VertexArray *) handle;
790 M3G_VALIDATE_OBJECT(array);
792 M3G_ASSERT(array->numLocks == 0);
795 if (array->mapCount) {
796 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_OPERATION);
800 m3gRaiseError(M3G_INTERFACE(array), M3G_NULL_POINTER);
803 if (first < 0 || first + count > array->vertexCount) {
804 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_INDEX);
807 if (count < 0 || srcLength < count * array->elementSize) {
808 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_VALUE);
812 /* Copy source data according to destination array type */
814 int values = count * array->elementSize;
816 switch (array->elementType) {
818 case GL_UNSIGNED_BYTE:
819 if (type != M3G_BYTE) {
820 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_OPERATION);
825 ((GLubyte *)m3gMapObject(M3G_INTERFACE(array),
827 + first * array->stride;
828 GLubyte *srcByte = (GLubyte *) src;
830 M3G_ASSERT(array->elementSize >= 2 && array->elementSize <= 4);
831 M3G_ASSERT(array->stride == 4);
836 *dst++ = (M3Gubyte)((array->elementSize >= 3) ? *srcByte++ : 0x00);
837 *dst++ = (M3Gubyte)((array->elementSize == 4) ? *srcByte++ : 0xFF);
838 values -= array->elementSize;
844 case GL_UNSIGNED_SHORT:
845 if (type != M3G_SHORT) {
846 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_OPERATION);
851 ((GLushort *)m3gMapObject(M3G_INTERFACE(array),
853 + first * array->stride / 2;
854 GLushort *srcShort = (GLushort *) src;
855 M3G_ASSERT(array->stride == (GLsizei)(array->elementSize * sizeof(*dst)));
858 *dst++ = *srcShort++;
864 M3G_ASSERT(0); /* fatal internal error */
868 m3gUnmapObject(M3G_INTERFACE(array), array->data);
869 m3gInvalidateArray(array);
873 * \brief Get a range of vertex array elements
875 * \param handle array handle
876 * \param first index of first vertex to set
877 * \param count number of total vertices to set
878 * \param dstLength length of destination data
879 * \param type data type of destination data
880 * \param dst destination data
882 M3G_API void m3gGetVertexArrayElements(M3GVertexArray handle,
883 M3Gint first, M3Gsizei count,
884 M3Gsizei dstLength, M3Gdatatype type, void *dst)
886 VertexArray *array = (VertexArray *) handle;
887 M3G_VALIDATE_OBJECT(array);
889 M3G_ASSERT(array->numLocks == 0);
892 if (array->mapCount) {
893 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_OPERATION);
897 m3gRaiseError(M3G_INTERFACE(array), M3G_NULL_POINTER);
900 if (first < 0 || first + count > array->vertexCount) {
901 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_INDEX);
904 if (count < 0 || dstLength < count * array->elementSize) {
905 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_VALUE);
909 /* Data according to destination array type */
911 int values = count * array->elementSize;
913 switch (array->elementType) {
915 case GL_UNSIGNED_BYTE:
916 if (type != M3G_BYTE) {
917 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_OPERATION);
922 ((GLubyte *)m3gMapObject(M3G_INTERFACE(array),
924 + first * array->stride;
925 GLubyte *dstByte = (GLubyte *) dst;
927 M3G_ASSERT(array->elementSize >= 2 && array->elementSize <= 4);
928 M3G_ASSERT(array->stride == 4);
933 if (array->elementSize >= 3) {
936 if (array->elementSize == 4) {
940 values -= array->elementSize;
946 case GL_UNSIGNED_SHORT:
947 if (type != M3G_SHORT) {
948 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_OPERATION);
953 ((GLushort *)m3gMapObject(M3G_INTERFACE(array),
955 + first * array->stride / 2;
956 GLushort *dstShort = (GLushort *) dst;
957 M3G_ASSERT(array->stride == (GLsizei)(array->elementSize * sizeof(*src)));
960 *dstShort++ = *src++;
966 M3G_ASSERT(0); /* fatal internal error */
970 m3gUnmapObject(M3G_INTERFACE(array), array->data);
974 * \brief Transform vertex array with
975 * given transform and w.
977 * \param handle array handle
978 * \param transform transform
979 * \param out output array to fill in
980 * \param outLength length of the output array
983 M3G_API void m3gTransformArray(M3GVertexArray handle,
984 M3GMatrix *transform,
985 M3Gfloat *out, M3Gint outLength,
990 M3Gfloat *outPtr = out;
993 VertexArray *array = (VertexArray *) handle;
994 M3G_VALIDATE_OBJECT(array);
996 /* Check for errors */
997 if (outLength < (4 * array->vertexCount) ||
998 array->elementSize == 4) {
999 m3gRaiseError(M3G_INTERFACE(array), M3G_INVALID_VALUE);
1003 switch(array->elementType) {
1005 case GL_UNSIGNED_BYTE:
1006 bptr = (M3Gbyte *)m3gMapObject(M3G_INTERFACE(array), array->data);
1008 for (i = 0; i < array->vertexCount * 4; i += 4) {
1009 vec.x = bptr[i + 0];
1010 vec.y = bptr[i + 1];
1012 if (array->elementSize == 3) {
1013 vec.z = bptr[i + 2];
1015 vec.w = (M3Gfloat)w;
1017 m3gTransformVec4(transform, &vec);
1027 case GL_UNSIGNED_SHORT:
1028 sptr = (M3Gshort *)m3gMapObject(M3G_INTERFACE(array), array->data);
1030 for (i = 0; i < array->vertexCount * array->elementSize; i += array->elementSize) {
1031 vec.x = sptr[i + 0];
1032 vec.y = sptr[i + 1];
1034 if (array->elementSize == 3) {
1035 vec.z = sptr[i + 2];
1037 vec.w = (M3Gfloat)w;
1039 m3gTransformVec4(transform, &vec);
1048 m3gUnmapObject(M3G_INTERFACE(array), array->data);
1051 #undef DIRTY_ALPHA_FACTOR