14 #include <OpenGL/CGLMacro.h>
16 #define glGenVertexArrays glGenVertexArraysAPPLE
17 #define glBindVertexArray glBindVertexArrayAPPLE
18 #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
27 "description" :
"A 3D shape represented by a set of vertices with associated normals and other per-vertex data.",
28 "keywords" : [
"mesh",
"vertex" ],
72 VuoPoint4d *positions, VuoPoint4d *normals, VuoPoint4d *tangents, VuoPoint4d *bitangents, VuoPoint4d *textureCoordinates,
96 VuoSubmesh VuoSubmesh_makeGl(
unsigned int vertexCount,
unsigned int combinedBuffer,
unsigned int combinedBufferSize,
unsigned int combinedBufferStride,
void *normalOffset,
void *tangentOffset,
void *bitangentOffset,
void *textureCoordinateOffset,
unsigned int elementCount,
unsigned int elementBuffer,
unsigned int elementBufferSize,
VuoMesh_ElementAssemblyMethod elementAssemblyMethod)
111 sm.
glUpload.combinedBuffer = combinedBuffer;
112 sm.
glUpload.combinedBufferSize = combinedBufferSize;
113 sm.
glUpload.combinedBufferStride = combinedBufferStride;
114 sm.
glUpload.normalOffset = normalOffset;
115 sm.
glUpload.tangentOffset = tangentOffset;
116 sm.
glUpload.bitangentOffset = bitangentOffset;
117 sm.
glUpload.textureCoordinateOffset = textureCoordinateOffset;
118 sm.
glUpload.elementBuffer = elementBuffer;
119 sm.
glUpload.elementBufferSize = elementBufferSize;
132 return GL_TRIANGLE_STRIP;
134 return GL_TRIANGLE_FAN;
138 return GL_LINE_STRIP;
213 if (elementCount == 0)
219 if (elementCount % 3 != 0)
221 VUserLog(
"Warning: VuoMesh_IndividualTriangles requires elementCount %% 3 == 0, but this mesh has %ld. Rounding down.", elementCount);
222 return (elementCount/3)*3;
227 if (elementCount < 3)
229 VUserLog(
"Warning: VuoMesh_TriangleStrip requires elementCount >= 3, but this mesh only has %ld.", elementCount);
235 if (elementCount < 3)
237 VUserLog(
"Warning: VuoMesh_TriangleFan requires elementCount >= 3, but this mesh only has %ld.", elementCount);
243 if (elementCount % 2 != 0)
245 VUserLog(
"Warning: VuoMesh_IndividualLines requires elementCount %% 2 == 0, but this mesh has %ld. Rounding down.", elementCount);
246 return (elementCount/2)*2;
251 if (elementCount < 2)
253 VUserLog(
"Warning: VuoMesh_LineStrip requires elementCount >= 2, but this mesh only has %ld.", elementCount);
302 if (submeshCount == 0)
338 unsigned int bufferCount = 0;
342 unsigned int normalOffset = 0;
344 normalOffset = bufferCount++;
345 mesh->
submeshes[i].
glUpload.normalOffset = (
void *)(normalOffset*
sizeof(VuoPoint4d));
347 unsigned int tangentOffset = 0;
349 tangentOffset = bufferCount++;
350 mesh->
submeshes[i].
glUpload.tangentOffset = (
void *)(tangentOffset*
sizeof(VuoPoint4d));
352 unsigned int bitangentOffset = 0;
354 bitangentOffset = bufferCount++;
355 mesh->
submeshes[i].
glUpload.bitangentOffset = (
void *)(bitangentOffset*
sizeof(VuoPoint4d));
357 unsigned int textureCoordinateOffset = 0;
359 textureCoordinateOffset = bufferCount++;
360 mesh->
submeshes[i].
glUpload.textureCoordinateOffset = (
void *)(textureCoordinateOffset*
sizeof(VuoPoint4d));
362 unsigned long singleBufferSize =
sizeof(VuoPoint4d)*meshItem.
vertexCount;
363 VuoPoint4d *combinedData = (VuoPoint4d *)malloc(singleBufferSize*bufferCount);
367 for (
unsigned long i = 0; i < meshItem.
vertexCount; ++i)
369 combinedData[i*bufferCount] = meshItem.
positions[i];
371 combinedData[i*bufferCount+normalOffset] = meshItem.
normals[i];
373 combinedData[i*bufferCount+tangentOffset] = meshItem.
tangents[i];
375 combinedData[i*bufferCount+bitangentOffset] = meshItem.
bitangents[i];
386 glBufferSubData(GL_ARRAY_BUFFER, 0, singleBufferSize * bufferCount, combinedData);
394 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->
submeshes[i].
glUpload.elementBuffer);
395 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0,
sizeof(
unsigned int) * meshItem.
elementCount, meshItem.
elements);
398 glBindBuffer(GL_ARRAY_BUFFER, 0);
404 glFlushRenderAPPLE();
498 unsigned int positionCount = 4;
499 VuoPoint4d *positions = (VuoPoint4d *)malloc(
sizeof(VuoPoint4d) * positionCount);
505 VuoPoint4d *textureCoordinates = (VuoPoint4d *)malloc(
sizeof(VuoPoint4d) * positionCount);
511 unsigned int elementCount = 6;
512 unsigned int *elements = (
unsigned int *)malloc(
sizeof(
unsigned int) * elementCount);
523 positions, NULL, NULL, NULL, textureCoordinates,
538 float angle = M_PI/2. + i * 2*M_PI/3.;
575 static VuoMesh sharedQuadWithNormals;
576 static dispatch_once_t token = 0;
577 dispatch_once(&token, ^{
581 return sharedQuadWithNormals;
593 static VuoMesh sharedQuadWithoutNormals;
594 static dispatch_once_t token = 0;
595 dispatch_once(&token, ^{
599 return sharedQuadWithoutNormals;
609 static VuoMesh sharedEquilateralTriangle;
610 static dispatch_once_t token = 0;
611 dispatch_once(&token, ^{
615 return sharedEquilateralTriangle;
625 VuoPoint4d positions[] = (VuoPoint4d[]){
658 VuoPoint4d normals[] = (VuoPoint4d[]){
691 VuoPoint4d tangents[] = (VuoPoint4d[]){
724 VuoPoint4d bitangents[] = (VuoPoint4d[]){
757 VuoPoint4d textureCoordinates[] = (VuoPoint4d[]){
790 unsigned int elements[] = (
unsigned int[]){
812 memcpy(sm.
positions, positions,
sizeof(positions));
813 memcpy(sm.
normals, normals,
sizeof(normals));
814 memcpy(sm.
tangents, tangents,
sizeof(tangents));
815 memcpy(sm.
bitangents, bitangents,
sizeof(bitangents));
817 memcpy(sm.
elements, elements,
sizeof(elements));
830 static dispatch_once_t token = 0;
831 dispatch_once(&token, ^{
846 VuoPoint4d *positions4d = (VuoPoint4d *)malloc(
sizeof(VuoPoint4d) * count);
847 unsigned int *elements = (
unsigned int *)malloc(
sizeof(
unsigned int) * count);
848 for (
unsigned long i = 0; i < count; ++i)
850 VuoPoint2d xy = positionValues[i];
851 positions4d[i] = (VuoPoint4d){xy.x, xy.y, 0, 1};
856 positions4d, NULL, NULL, NULL, NULL,
857 count, elements, elementAssemblyMethod);
870 VuoPoint4d *positions4d = (VuoPoint4d *)malloc(
sizeof(VuoPoint4d) * count);
871 unsigned int *elements = (
unsigned int *)malloc(
sizeof(
unsigned int) * count);
872 for (
unsigned long i = 0; i < count; ++i)
874 VuoPoint3d xyz = positionValues[i];
875 positions4d[i] = (VuoPoint4d){xyz.x, xyz.y, xyz.z, 1};
880 positions4d, NULL, NULL, NULL, NULL,
881 count, elements, elementAssemblyMethod);
902 unsigned long attributeByteCount =
sizeof(VuoPoint4d)*copiedSubmesh.
vertexCount;
906 copiedSubmesh.
positions = (VuoPoint4d *)malloc(attributeByteCount);
914 copiedSubmesh.
normals = (VuoPoint4d *)malloc(attributeByteCount);
915 memcpy(copiedSubmesh.
normals, submesh.
normals, attributeByteCount);
922 copiedSubmesh.
tangents = (VuoPoint4d *)malloc(attributeByteCount);
930 copiedSubmesh.
bitangents = (VuoPoint4d *)malloc(attributeByteCount);
947 unsigned long elementByteCount =
sizeof(
unsigned int)*submesh.
elementCount;
948 copiedSubmesh.
elements = (
unsigned int *)malloc(elementByteCount);
962 copiedMesh->
submeshes[i] = copiedSubmesh;
1006 copiedMesh->
submeshes[i] = copiedSubmesh;
1017 if (strcmp(elementAssemblyMethodString,
"individualTriangles")==0)
1019 else if (strcmp(elementAssemblyMethodString,
"triangleStrip")==0)
1021 else if (strcmp(elementAssemblyMethodString,
"triangleFan")==0)
1023 else if (strcmp(elementAssemblyMethodString,
"individualLines")==0)
1025 else if (strcmp(elementAssemblyMethodString,
"lineStrip")==0)
1027 else if (strcmp(elementAssemblyMethodString,
"points")==0)
1040 switch (elementAssemblyMethod)
1043 return "individualTriangles";
1045 return "triangleStrip";
1047 return "triangleFan";
1049 return "individualLines";
1062 if (submesh.
glUpload.combinedBufferStride)
1063 return submesh.
glUpload.combinedBufferStride;
1065 int bufferCount = 0;
1069 if (submesh.
glUpload.tangentOffset)
1071 if (submesh.
glUpload.bitangentOffset)
1073 if (submesh.
glUpload.textureCoordinateOffset)
1076 return sizeof(VuoPoint4d) * bufferCount;
1082 VuoPoint4d *
extractElements(CGLContextObj cgl_ctx,
VuoSubmesh *submesh,
unsigned int vertexCount,
unsigned int bufferStrideInBytes,
unsigned int bufferIndex)
1084 unsigned int bufferStrideInFloats = bufferStrideInBytes /
sizeof(GLfloat);
1085 GLfloat *feedback = (GLfloat *)malloc(submesh->
glUpload.combinedBufferSize);
1086 glGetBufferSubData(GL_ARRAY_BUFFER, 0, submesh->
glUpload.combinedBufferSize, feedback);
1088 VuoPoint4d *elements = (VuoPoint4d*)malloc(
sizeof(VuoPoint4d)*vertexCount);
1090 for (
int vertex = 0; vertex < vertexCount; vertex++)
1092 elements[vertex] = (VuoPoint4d)
1094 feedback[vertex*bufferStrideInFloats + 0 + (bufferIndex*4)],
1095 feedback[vertex*bufferStrideInFloats + 1 + (bufferIndex*4)],
1096 feedback[vertex*bufferStrideInFloats + 2 + (bufferIndex*4)],
1097 feedback[vertex*bufferStrideInFloats + 3 + (bufferIndex*4)]
1109 void VuoSubmeshMesh_download(
VuoSubmesh *submesh)
__attribute__ ((deprecated(
"VuoSubmeshMesh_download is deprecated, please use VuoSubmesh_download instead.")));
1110 void VuoSubmeshMesh_download(
VuoSubmesh *submesh)
1128 glBindBuffer(GL_ARRAY_BUFFER, submesh->
glUpload.combinedBuffer);
1134 int bufferIndex = 0;
1151 glBindBuffer(GL_ARRAY_BUFFER, 0);
1156 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, submesh->
glUpload.elementBuffer);
1157 glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, submesh->
glUpload.elementBufferSize, submesh->
elements);
1158 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1168 VuoPoint3d min, max;
1178 if(vertexCount > 0 && !init)
1184 for(
int n = 0; n < vertexCount; n++)
1188 min.x =
MIN(p.x, min.x);
1189 min.y =
MIN(p.y, min.y);
1190 min.z =
MIN(p.z, min.z);
1192 max.x =
MAX(p.x, max.x);
1193 max.y =
MAX(p.y, max.y);
1194 max.z =
MAX(p.z, max.z);
1199 return VuoBox_make((min + max) / (VuoPoint3d)(2.), max - min);
1201 return VuoBox_make( (VuoPoint3d){0,0,0}, (VuoPoint3d){0,0,0} );
1232 if (json_object_object_get_ex(js,
"pointer", &o))
1233 return (
VuoMesh)json_object_get_int64(o);
1248 json_object_object_add(js,
"pointer", json_object_new_int64((int64_t)value));
1274 char * zero = strdup(
"0 vertices");
1279 const char * objectString =
"";
1280 const char * assemblyMethod =
" (unknown element assembly method)";
1283 assemblyMethod =
", ";
1284 objectString =
"triangle";
1289 assemblyMethod =
" in a strip of ";
1290 objectString =
"triangle";
1294 assemblyMethod =
" in a fan of ";
1295 objectString =
"triangle";
1299 assemblyMethod =
", ";
1300 objectString =
"line";
1304 assemblyMethod =
" in a strip of ";
1305 objectString =
"line";
1309 assemblyMethod =
", ";
1310 objectString =
"point";
1313 const char * vertexCountString = value.
vertexCount==1 ?
"vertex" :
"vertices";
1314 const char * objectStringPlural = objectCount==1 ?
"" :
"s";
1316 char *firstPosition = NULL;
1320 char *summary =
VuoText_format(
"<div>%u %s%s%lu %s%s</div>%s<div>%s positions</div><div>%s normals</div><div>%s tangents</div><div>%s bitangents</div><div>%s texture coordinates</div>",
1321 value.
vertexCount, vertexCountString, assemblyMethod, objectCount, objectString, objectStringPlural,
1322 firstPosition ? firstPosition :
"",
1329 free(firstPosition);
1340 return strdup(
"Empty mesh");
1342 char *prefix =
"Mesh containing: <ul>";
1343 unsigned int prefixBytes = strlen(prefix);
1345 const int maxSubmeshCount = 20;
1346 unsigned int submeshCount =
MIN(value->
submeshCount, maxSubmeshCount);
1347 char **submeshes = (
char **)malloc(submeshCount *
sizeof(
char *));
1348 unsigned int submeshBytes = 0;
1349 for (
unsigned int i = 0; i < submeshCount; ++i)
1352 submeshes[i] = (
char *)malloc((strlen(s) + 4 + 5 + 1));
1353 submeshes[i][0] = 0;
1354 strncat(submeshes[i],
"<li>", 4);
1355 strncat(submeshes[i], s, strlen(s));
1356 strncat(submeshes[i],
"</li>", 5);
1357 submeshBytes += strlen(submeshes[i]);
1361 char *suffix = (value->
submeshCount > maxSubmeshCount ?
"<li>...</li></ul>" :
"</ul>");
1362 unsigned int suffixBytes = strlen(suffix);
1364 char *summary = (
char *)malloc(prefixBytes + submeshBytes + suffixBytes + 1);
1366 strncat(summary, prefix, prefixBytes);
1367 for (
unsigned int i = 0; i < submeshCount; ++i)
1368 strncat(summary, submeshes[i], strlen(submeshes[i]));
1369 strncat(summary, suffix, suffixBytes);
1371 for (
unsigned int i = 0; i < submeshCount; ++i)