13#include <unordered_map>
16template<
class V,
class N,
class C,
class T>
19 bVertsChanged =
false;
20 bColorsChanged =
false;
21 bNormalsChanged =
false;
22 bTexCoordsChanged =
false;
23 bIndicesChanged =
false;
33template<
class V,
class N,
class C,
class T>
35 bColorsChanged =
false;
36 bNormalsChanged =
false;
37 bTexCoordsChanged =
false;
48template<
class V,
class N,
class C,
class T>
50 if(!vertices.empty()){
55 bColorsChanged =
true;
59 bNormalsChanged =
true;
62 if(!texCoords.empty()){
63 bTexCoordsChanged =
true;
67 bIndicesChanged =
true;
75template<
class V,
class N,
class C,
class T>
78 bVertsChanged =
false;
88template<
class V,
class N,
class C,
class T>
91 bColorsChanged =
false;
101template<
class V,
class N,
class C,
class T>
104 bNormalsChanged =
false;
114template<
class V,
class N,
class C,
class T>
116 if(bTexCoordsChanged){
117 bTexCoordsChanged =
false;
127template<
class V,
class N,
class C,
class T>
130 bIndicesChanged =
false;
141template<
class V,
class N,
class C,
class T>
143 return !vertices.empty();
149template<
class V,
class N,
class C,
class T>
151 return !colors.empty();
157template<
class V,
class N,
class C,
class T>
159 return !normals.empty();
165template<
class V,
class N,
class C,
class T>
167 return !texCoords.empty();
173template<
class V,
class N,
class C,
class T>
175 return !indices.empty();
183template<
class V,
class N,
class C,
class T>
185 vertices.push_back(v);
186 bVertsChanged =
true;
193template<
class V,
class N,
class C,
class T>
195 vertices.insert(vertices.end(),verts.begin(),verts.end());
196 bVertsChanged =
true;
203template<
class V,
class N,
class C,
class T>
205 vertices.insert(vertices.end(),verts,verts+amt);
206 bVertsChanged =
true;
213template<
class V,
class N,
class C,
class T>
216 bColorsChanged =
true;
223template<
class V,
class N,
class C,
class T>
225 colors.insert(colors.end(),cols.begin(),cols.end());
226 bColorsChanged =
true;
233template<
class V,
class N,
class C,
class T>
235 colors.insert(colors.end(),cols,cols+amt);
236 bColorsChanged =
true;
243template<
class V,
class N,
class C,
class T>
245 normals.push_back(n);
246 bNormalsChanged =
true;
253template<
class V,
class N,
class C,
class T>
255 normals.insert(normals.end(),norms.begin(),norms.end());
256 bNormalsChanged =
true;
263template<
class V,
class N,
class C,
class T>
265 normals.insert(normals.end(),norms,norms+amt);
266 bNormalsChanged =
true;
273template<
class V,
class N,
class C,
class T>
276 texCoords.push_back(t);
277 bTexCoordsChanged =
true;
284template<
class V,
class N,
class C,
class T>
286 texCoords.insert(texCoords.end(),tCoords.begin(),tCoords.end());
287 bTexCoordsChanged =
true;
294template<
class V,
class N,
class C,
class T>
296 texCoords.insert(texCoords.end(),tCoords,tCoords+amt);
297 bTexCoordsChanged =
true;
304template<
class V,
class N,
class C,
class T>
312template<
class V,
class N,
class C,
class T>
314 indices.push_back(i);
315 bIndicesChanged =
true;
322template<
class V,
class N,
class C,
class T>
324 indices.insert(indices.end(),inds.begin(),inds.end());
325 bIndicesChanged =
true;
332template<
class V,
class N,
class C,
class T>
334 indices.insert(indices.end(),inds,inds+amt);
335 bIndicesChanged =
true;
342template<
class V,
class N,
class C,
class T>
353template<
class V,
class N,
class C,
class T>
355 if(index >= vertices.size()){
356 ofLogError(
"ofMesh") <<
"removeVertex(): ignoring out of range index " << index <<
", number of vertices is" << vertices.size();
358 vertices.erase(vertices.begin() + index);
359 bVertsChanged =
true;
364template<
class V,
class N,
class C,
class T>
366 if(startIndex >= vertices.size() || endIndex > vertices.size()){
367 ofLogError(
"ofMesh") <<
"removeVertex(): ignoring out of range startIndex " << startIndex <<
" endIndex " << endIndex <<
", number of vertices is" << vertices.size();
369 vertices.erase(vertices.begin() + startIndex, vertices.begin() + endIndex);
370 bVertsChanged =
true;
378template<
class V,
class N,
class C,
class T>
380 if(index >= normals.size()){
381 ofLogError(
"ofMesh") <<
"removeNormal(): ignoring out of range index " << index <<
", number of normals is" << normals.size();
383 normals.erase(normals.begin() + index);
384 bNormalsChanged =
true;
389template<
class V,
class N,
class C,
class T>
391 if(startIndex >= normals.size() || endIndex > normals.size()){
392 ofLogError(
"ofMesh") <<
"removeNormal(): ignoring out of range beginIndex " << startIndex <<
" endIndex " << endIndex <<
", number of normals is" << normals.size();
394 normals.erase(normals.begin() + startIndex, normals.begin() + endIndex);
395 bNormalsChanged =
true;
402template<
class V,
class N,
class C,
class T>
404 if(index >= colors.size()){
405 ofLogError(
"ofMesh") <<
"removeColor(): ignoring out of range index " << index <<
", number of colors is" << colors.size();
407 colors.erase(colors.begin() + index);
408 bColorsChanged =
true;
413template<
class V,
class N,
class C,
class T>
415 if(startIndex >= colors.size() || endIndex > colors.size()){
416 ofLogError(
"ofMesh") <<
"removeColor(): ignoring out of range startIndex " << startIndex <<
" endIndex " << endIndex <<
", number of colors is" << colors.size();
418 colors.erase(colors.begin() + startIndex, colors.begin() + endIndex);
419 bColorsChanged =
true;
427template<
class V,
class N,
class C,
class T>
429 if(index >= texCoords.size()){
430 ofLogError(
"ofMesh") <<
"removeTexCoord(): ignoring out of range index " << index <<
", number of tex coords is" << texCoords.size();
432 texCoords.erase(texCoords.begin() + index);
433 bTexCoordsChanged =
true;
438template<
class V,
class N,
class C,
class T>
440 if(startIndex >= texCoords.size() || endIndex >= texCoords.size()){
441 ofLogError(
"ofMesh") <<
"removeTexCoord(): ignoring out of range startIndex " << startIndex <<
" endIndex " << endIndex <<
", number of tex coords is" << texCoords.size();
443 texCoords.erase(texCoords.begin() + startIndex, texCoords.begin() + endIndex);
444 bTexCoordsChanged =
true;
453template<
class V,
class N,
class C,
class T>
455 if(index >= indices.size()){
456 ofLogError(
"ofMesh") <<
"removeIndex(): ignoring out of range index " << index <<
", number of indices is" << indices.size();
458 indices.erase(indices.begin() + index);
459 bIndicesChanged =
true;
464template<
class V,
class N,
class C,
class T>
466 if(startIndex >= indices.size() || endIndex > indices.size()){
467 ofLogError(
"ofMesh") <<
"removeIndex(): ignoring out of range startIndex " << startIndex <<
" endIndex " << endIndex <<
", number of indices is" << indices.size();;
469 indices.erase(indices.begin() + startIndex, indices.begin() + endIndex);
470 bIndicesChanged =
true;
481template<
class V,
class N,
class C,
class T>
489template<
class V,
class N,
class C,
class T>
497template<
class V,
class N,
class C,
class T>
505template<
class V,
class N,
class C,
class T>
513template<
class V,
class N,
class C,
class T>
521template<
class V,
class N,
class C,
class T>
523 return vertices.size();
529template<
class V,
class N,
class C,
class T>
531 return colors.size();
537template<
class V,
class N,
class C,
class T>
539 return normals.size();
545template<
class V,
class N,
class C,
class T>
547 return texCoords.size();
553template<
class V,
class N,
class C,
class T>
555 return indices.size();
579template<
class V,
class N,
class C,
class T>
581 return vertices.data();
587template<
class V,
class N,
class C,
class T>
589 return colors.data();
595template<
class V,
class N,
class C,
class T>
597 return normals.data();
603template<
class V,
class N,
class C,
class T>
605 return texCoords.data();
611template<
class V,
class N,
class C,
class T>
613 return indices.data();
620template<
class V,
class N,
class C,
class T>
622 return vertices.data();
628template<
class V,
class N,
class C,
class T>
630 return colors.data();
636template<
class V,
class N,
class C,
class T>
638 return normals.data();
644template<
class V,
class N,
class C,
class T>
646 return texCoords.data();
652template<
class V,
class N,
class C,
class T>
654 return indices.data();
658template<
class V,
class N,
class C,
class T>
660 bVertsChanged =
true;
666template<
class V,
class N,
class C,
class T>
668 bColorsChanged =
true;
674template<
class V,
class N,
class C,
class T>
676 bNormalsChanged =
true;
682template<
class V,
class N,
class C,
class T>
684 bTexCoordsChanged =
true;
690template<
class V,
class N,
class C,
class T>
692 bIndicesChanged =
true;
698template<
class V,
class N,
class C,
class T>
704template<
class V,
class N,
class C,
class T>
710template<
class V,
class N,
class C,
class T>
716template<
class V,
class N,
class C,
class T>
722template<
class V,
class N,
class C,
class T>
783template<
class V,
class N,
class C,
class T>
785 if(vertices.size() == 0) {
786 ofLogWarning(
"ofMesh") <<
"getCentroid(): mesh has no vertices, returning glm::vec3(0, 0, 0)";
787 return glm::vec3(0, 0, 0);
794 sum /= vertices.size();
802template<
class V,
class N,
class C,
class T>
804 bIndicesChanged =
true;
811template<
class V,
class N,
class C,
class T>
814 bVertsChanged =
true;
815 bIndicesChanged =
true;
822template<
class V,
class N,
class C,
class T>
825 bNormalsChanged =
true;
832template<
class V,
class N,
class C,
class T>
835 bColorsChanged =
true;
842template<
class V,
class N,
class C,
class T>
844 texCoords[index] = t;
845 bTexCoordsChanged =
true;
852template<
class V,
class N,
class C,
class T>
854 indices[index] = val;
855 bIndicesChanged =
true;
862template<
class V,
class N,
class C,
class T>
864 bIndicesChanged =
true;
866 indices.resize(vertices.size());
877template<
class V,
class N,
class C,
class T>
886template<
class V,
class N,
class C,
class T>
889 bNormalsChanged=
true;
896template<
class V,
class N,
class C,
class T>
906template<
class V,
class N,
class C,
class T>
909 bTexCoordsChanged=
true;
916template<
class V,
class N,
class C,
class T>
919 bIndicesChanged =
true;
926template<
class V,
class N,
class C,
class T>
934template<
class V,
class N,
class C,
class T>
942template<
class V,
class N,
class C,
class T>
950template<
class V,
class N,
class C,
class T>
958template<
class V,
class N,
class C,
class T>
960 if(getNumVertices()==0)
return;
967template<
class V,
class N,
class C,
class T>
975template<
class V,
class N,
class C,
class T>
983template<
class V,
class N,
class C,
class T>
991template<
class V,
class N,
class C,
class T>
999template<
class V,
class N,
class C,
class T>
1007template<
class V,
class N,
class C,
class T>
1009 useTextures =
false;
1015template<
class V,
class N,
class C,
class T>
1023template<
class V,
class N,
class C,
class T>
1031template<
class V,
class N,
class C,
class T>
1039template<
class V,
class N,
class C,
class T>
1047template<
class V,
class N,
class C,
class T>
1055template<
class V,
class N,
class C,
class T>
1064template<
class V,
class N,
class C,
class T>
1081 indices.push_back(index+prevNumVertices);
1090template<
class V,
class N,
class C,
class T>
1093 auto & data = *
this;
1099 int orderVertices=-1;
1100 int orderIndices=-1;
1110 bool colorTypeIsUChar =
false;
1129 std::vector<Attribute> meshDefinition;
1132 State state = Header;
1139 error =
"wrong format, expecting 'ply'";
1145 if(*line!=
"format ascii 1.0"){
1146 error =
"wrong format, expecting 'format ascii 1.0'";
1150 for(;line != lines.
end(); ++line){
1152 std::string lineStr = *line;
1153 if(lineStr.find(
"comment")==0 || lineStr.empty()){
1157 if((state==Header || state==FaceDef) && lineStr.find(
"element vertex")==0){
1159 orderVertices = std::max(orderIndices, 0)+1;
1160 data.getVertices().resize(ofTo<size_t>(lineStr.substr(15)));
1164 if((state==Header || state==VertexDef) && lineStr.find(
"element face")==0){
1166 orderIndices = std::max(orderVertices, 0)+1;
1167 data.getIndices().resize(ofTo<size_t>(lineStr.substr(13))*3);
1171 if(state==VertexDef && (lineStr.find(
"property float x")==0 || lineStr.find(
"property float y")==0 || lineStr.find(
"property float z")==0
1172 || lineStr.find(
"property double x")==0 || lineStr.find(
"property double y")==0 || lineStr.find(
"property double z")==0)){
1173 meshDefinition.push_back(Position);
1174 vertexCoordsFound++;
1178 if(state==VertexDef && (lineStr.find(
"property float r")==0 || lineStr.find(
"property float g")==0 || lineStr.find(
"property float b")==0 || lineStr.find(
"property float a")==0)){
1180 meshDefinition.push_back(Color);
1181 data.getColors().resize(data.getVertices().size());
1185 if(state==VertexDef && (lineStr.find(
"property uchar red")==0 || lineStr.find(
"property uchar green")==0 || lineStr.find(
"property uchar blue")==0 || lineStr.find(
"property uchar alpha")==0)){
1186 colorTypeIsUChar =
true;
1188 meshDefinition.push_back(Color);
1189 data.getColors().resize(data.getVertices().size());
1193 if(state==VertexDef && (lineStr.find(
"property float u")==0 || lineStr.find(
"property float v")==0|| lineStr.find(
"property float s")==0 || lineStr.find(
"property float t")==0)){
1195 meshDefinition.push_back(TexCoord);
1196 data.getTexCoords().resize(data.getVertices().size());
1200 if(state==VertexDef && (lineStr.find(
"property float nx")==0 || lineStr.find(
"property float ny")==0 || lineStr.find(
"property float nz")==0)){
1201 normalsCoordsFound++;
1202 meshDefinition.push_back(Normal);
1203 if (normalsCoordsFound==3) data.getNormals().resize(data.getVertices().size());
1207 if(state==FaceDef && lineStr.find(
"property list")!=0 && lineStr!=
"end_header"){
1208 error =
"wrong face definition";
1212 if(lineStr==
"end_header"){
1213 if(data.hasColors() && colorCompsFound!=3 && colorCompsFound!=4){
1214 error =
"data has color coordiantes but not correct number of components. Found " +
ofToString(colorCompsFound) +
" expecting 3 or 4";
1217 if(data.hasNormals() && normalsCoordsFound!=3){
1218 error =
"data has normal coordiantes but not correct number of components. Found " +
ofToString(normalsCoordsFound) +
" expecting 3";
1221 if(!data.hasVertices()){
1222 ofLogWarning(
"ofMesh") <<
"load(): mesh loaded from \"" << path <<
"\" has no vertices";
1224 if(orderVertices==-1) orderVertices=9999;
1225 if(orderIndices==-1) orderIndices=9999;
1227 if(orderVertices < orderIndices){
1235 if(state==Vertices){
1236 if(data.getNumVertices()<=currentVertex){
1237 error =
"found more vertices: " +
ofToString(currentVertex+1) +
" than specified in header: " +
ofToString(data.getNumVertices());
1240 std::stringstream sline(lineStr);
1249 for(
auto s:meshDefinition){
1252 sline >> *(&data.getVertices()[currentVertex].x + (vAttr++)%vertexCoordsFound);
1255 if (colorTypeIsUChar){
1258 *(&data.getColors()[currentVertex].r + (cAttr++)%colorCompsFound) =
c/255.f;
1260 sline >> *(&data.getColors()[currentVertex].r + (cAttr++)%colorCompsFound);
1264 sline >> *(&data.getNormals()[currentVertex].x + (nAttr++)%normalsCoordsFound);
1267 sline >> *(&data.getTexCoords()[currentVertex].x + (tAttr++)%texCoordsFound);
1273 if (vAttr != vertexCoordsFound || cAttr!= colorCompsFound || nAttr!=normalsCoordsFound || tAttr!=texCoordsFound){
1274 error =
"attribute data does not match definition in header";
1279 if(currentVertex==data.getNumVertices()){
1280 if(orderVertices<orderIndices){
1290 if(data.getNumIndices()/3<currentFace){
1291 error =
"found more faces than specified in header";
1294 std::stringstream sline(lineStr);
1298 error =
"face not a triangle";
1303 data.getIndices()[currentFace*3] = i;
1305 data.getIndices()[currentFace*3+1] = i;
1307 data.getIndices()[currentFace*3+2] = i;
1310 if(currentFace==data.getNumIndices()/3){
1311 if(orderVertices<orderIndices){
1324 ofLogError(
"ofMesh") <<
"load(): " << lineNum <<
":" << error;
1325 ofLogError(
"ofMesh") <<
"load(): \"" << *line <<
"\"";
1330template<
class V,
class N,
class C,
class T>
1333 const auto & data = *
this;
1335 os <<
"ply" << std::endl;
1337 os <<
"format binary_little_endian 1.0" << std::endl;
1339 os <<
"format ascii 1.0" << std::endl;
1342 if(data.getNumVertices()){
1343 os <<
"element vertex " << data.getNumVertices() << std::endl;
1344 os <<
"property float x" << std::endl;
1345 os <<
"property float y" << std::endl;
1346 os <<
"property float z" << std::endl;
1347 if(data.getNumColors()){
1348 os <<
"property uchar red" << std::endl;
1349 os <<
"property uchar green" << std::endl;
1350 os <<
"property uchar blue" << std::endl;
1351 os <<
"property uchar alpha" << std::endl;
1353 if(data.getNumTexCoords()){
1354 os <<
"property float u" << std::endl;
1355 os <<
"property float v" << std::endl;
1357 if(data.getNumNormals()){
1358 os <<
"property float nx" << std::endl;
1359 os <<
"property float ny" << std::endl;
1360 os <<
"property float nz" << std::endl;
1364 uint8_t faceSize = 3;
1365 if(data.getNumIndices()){
1366 os <<
"element face " << data.getNumIndices() / faceSize << std::endl;
1367 os <<
"property list uchar int vertex_indices" << std::endl;
1369 os <<
"element face " << data.getNumVertices() / faceSize << std::endl;
1370 os <<
"property list uchar int vertex_indices" << std::endl;
1372 os <<
"element face " << data.getNumVertices() - 2 << std::endl;
1373 os <<
"property list uchar int vertex_indices" << std::endl;
1376 os <<
"end_header" << std::endl;
1378 for(std::size_t i = 0; i < data.getNumVertices(); i++){
1380 os.write((
char*) &data.getVertices()[i],
sizeof(V));
1382 os << data.getVertex(i).x <<
" " << data.getVertex(i).y <<
" " << data.getVertex(i).z;
1384 if(data.getNumColors()){
1386 ofColor cur = data.getColors()[i];
1388 os.write((
char*) &cur,
sizeof(
ofColor));
1390 os <<
" " << (int) cur.
r <<
" " << (
int) cur.
g <<
" " << (int) cur.
b <<
" " << (
int) cur.
a;
1393 if(data.getNumTexCoords()){
1395 os.write((
char*) &data.getTexCoords()[i],
sizeof(T));
1397 os <<
" " << data.getTexCoord(i).x <<
" " << data.getTexCoord(i).y;
1400 if(data.getNumNormals()){
1402 os.write((
char*) &data.getNormals()[i],
sizeof(V));
1404 os <<
" " << data.getNormal(i).x <<
" " << data.getNormal(i).y <<
" " << data.getNormal(i).z;
1412 if(data.getNumIndices()) {
1413 for(uint32_t i = 0; i < data.getNumIndices(); i += faceSize) {
1415 os.write((
char*) &faceSize,
sizeof(
unsigned char));
1416 os.write((
char*)&data.getIndices()[i], faceSize);
1418 os << (std::size_t) faceSize <<
" " << data.getIndex(i) <<
" " << data.getIndex(i+1) <<
" " << data.getIndex(i+2) << std::endl;
1422 for(uint32_t i = 0; i < data.getNumVertices(); i += faceSize) {
1423 uint32_t indices[] = {i, i + 1, i + 2};
1425 os.write((
char*) &faceSize,
sizeof(
unsigned char));
1426 os.write((
char*) indices,
sizeof(indices));
1428 os << (std::size_t) faceSize <<
" " << indices[0] <<
" " << indices[1] <<
" " << indices[2] << std::endl;
1432 for(uint32_t i = 0; i < data.getNumVertices() - 2; i += 2) {
1433 uint32_t indices1[] = {i, i + 1, i + 2};
1434 uint32_t indices2[] = {i + 1, i + 3, i + 2};
1436 os.write((
char*) &faceSize,
sizeof(
unsigned char));
1437 os.write((
char*) indices1,
sizeof(indices1));
1438 os.write((
char*) &faceSize,
sizeof(
unsigned char));
1439 os.write((
char*) indices2,
sizeof(indices2));
1441 os << (std::size_t) faceSize <<
" " << indices1[0] <<
" " << indices1[1] <<
" " << indices1[2] << std::endl;
1442 os << (std::size_t) faceSize <<
" " << indices2[0] <<
" " << indices2[1] <<
" " << indices2[2] << std::endl;
1452template<
class V,
class N,
class C,
class T>
1456 getColors().resize( getNumVertices() );
1459 for(
ofIndexType i = startIndex; i < endIndex; i++) {
1460 setColor( getIndex(i), color);
1466template<
class V,
class N,
class C,
class T>
1471 if(startIndex >= getNumIndices() ) {
1474 startVertIndex = getIndex( startIndex );
1477 if(endIndex >= getNumIndices() ) {
1479 endVertIndex = getNumVertices();
1481 endVertIndex = getIndex( endIndex );
1483 return getMeshForIndices(startIndex, endIndex, startVertIndex, endVertIndex );
1488template<
class V,
class N,
class C,
class T>
1494 mesh.
getVertices().assign( getVertices().begin()+startVertIndex, getVertices().begin()+endVertIndex );
1497 std::vector<ofFloatColor> colors;
1498 mesh.
getColors().assign( getColors().begin()+startVertIndex, getColors().begin()+endVertIndex );
1503 if( hasTexCoords() ) {
1504 mesh.
getTexCoords().assign( getTexCoords().begin()+startVertIndex, getTexCoords().begin()+endVertIndex );
1509 if( hasNormals() ) {
1510 mesh.
getNormals().assign( getNormals().begin()+startVertIndex, getNormals().begin()+endVertIndex );
1516 bool bFoundLessThanZero =
false;
1517 for(
ofIndexType i = startIndex; i < endIndex; i++) {
1519 if(getIndex(i)<offsetIndex){
1521 bFoundLessThanZero =
true;
1523 index = getIndex(i) - offsetIndex;
1528 if(bFoundLessThanZero) {
1529 ofLogWarning(
"ofMesh :: getMeshForIndices : found some indices less than 0, setting them to 0" );
1537template<
class V,
class N,
class C,
class T>
1540 std::vector<V> verts = getVertices();
1541 std::vector<ofIndexType> indices = getIndices();
1545 for(
ofIndexType j = 0; j < indices.size(); j++ ) {
1550 const V & v1 = verts[ i1 ];
1551 const V & v2 = verts[ i2 ];
1553 if( v1 == v2 && i1 != i2) {
1563 std::vector <V> newPoints;
1564 std::vector <ofIndexType> newIndexes;
1565 std::unordered_map <ofIndexType, bool> ptCreated;
1566 std::unordered_map <ofIndexType, ofIndexType> oldIndexNewIndex;
1568 std::vector<ofFloatColor> newColors;
1569 std::vector<ofFloatColor>& colors = getColors();
1570 std::vector<T> newTCoords;
1571 std::vector<T>& tcoords = getTexCoords();
1572 std::vector<N> newNormals;
1573 std::vector<N>& normals = getNormals();
1576 ptCreated[i] =
false;
1581 const auto & p = verts[ index ];
1583 if( ptCreated[index] ==
false ){
1584 oldIndexNewIndex[index] = newPoints.size();
1585 newPoints.push_back( p );
1587 newColors.push_back(colors[index]);
1589 if(hasTexCoords()) {
1590 newTCoords.push_back(tcoords[index]);
1593 newNormals.push_back(normals[index]);
1596 ptCreated[index] =
true;
1600 newIndexes.push_back( oldIndexNewIndex[index] );
1607 indices = newIndexes;
1610 addIndices(indices);
1612 addVertices( verts );
1616 addColors( newColors );
1619 if(hasTexCoords()) {
1621 addTexCoords( newTCoords );
1626 addNormals( newNormals );
1633template<
class V,
class N,
class C,
class T>
1635 const std::vector<ofMeshFace_<V,N,C,T>> & faces = getUniqueFaces();
1636 if(faces.size()>faceId){
1637 return faces[faceId];
1639 ofLogError() <<
"couldn't find face " << faceId;
1646template<
class V,
class N,
class C,
class T>
1651 faces.resize( indices.size()/3 );
1656 bool bHasColors = hasColors();
1657 bool bHasNormals = hasNormals();
1658 bool bHasTexcoords = hasTexCoords();
1661 for(std::size_t j = 0; j < indices.size(); j += 3) {
1663 for(std::size_t k = 0; k < 3; k++) {
1664 index = indices[j+k];
1677 ofLogWarning(
"ofMesh") <<
"getUniqueFaces(): only works with primitive mode OF_PRIMITIVE_TRIANGLES";
1680 bFacesDirty =
false;
1689template<
class V,
class N,
class C,
class T>
1692 std::vector<N> faceNormals;
1694 if( hasVertices() ) {
1695 if(vertices.size() > 3 && indices.size() > 3) {
1697 faceNormals.resize(indices.size()*3);
1699 faceNormals.resize(indices.size());
1703 for(
ofIndexType i = 0; i < indices.size(); i+=3) {
1704 face.
setVertex( 0, vertices[indices[i+0]] );
1705 face.
setVertex( 1, vertices[indices[i+1]] );
1706 face.
setVertex( 2, vertices[indices[i+2]] );
1724template<
class V,
class N,
class C,
class T>
1727 ofLogWarning(
"ofMesh") <<
"setFromTriangles(): ignoring empty tris vector";
1731 typename std::vector<ofMeshFace_<V,N,C,T>>::const_iterator it;
1733 vertices.resize(tris.size()*3 );
1736 if(it->hasNormals()){
1737 normals.resize(tris.size()*3);
1741 if(it->hasColors()){
1742 colors.resize(tris.size()*3);
1746 if(it->hasTexcoords()){
1747 texCoords.resize(tris.size()*3);
1753 for(it = tris.begin(); it != tris.end(); it++) {
1754 for(std::size_t k = 0; k < 3; k++) {
1755 vertices[i] = it->getVertex(k);
1756 if(it->hasTexcoords())
1757 texCoords[i] = it->getTexCoord(k);
1759 colors[i] = it->getColor(k);
1761 normals[i] = it->getFaceNormal();
1762 else if(it->hasNormals())
1763 normals[i] = it->getNormal(k);
1769 bVertsChanged =
true;
1770 bIndicesChanged =
true;
1771 bNormalsChanged =
true;
1772 bColorsChanged =
true;
1773 bTexCoordsChanged =
true;
1775 bFacesDirty =
false;
1781template<
class V,
class N,
class C,
class T>
1785 std::vector<ofMeshFace_<V,N,C,T>> triangles = getUniqueFaces();
1786 std::vector<V> verts;
1787 for(
ofIndexType i = 0; i < triangles.size(); i++) {
1789 verts.push_back( triangles[i].getVertex(j) );
1793 std::unordered_map<int, int> removeIds;
1795 float epsilon = .01f;
1799 const auto& v1 =
toGlm(verts[i]);
1800 const auto& v2 =
toGlm(verts[j]);
1801 if( glm::distance(v1, v2) <= epsilon ) {
1803 verts[i] = (v1+v2)/2.f;
1804 verts[j] = verts[i];
1812 std::unordered_map<std::string, std::vector<int> > vertHash;
1816 std::string xStr, yStr, zStr;
1819 xStr =
"x"+
ofToString(verts[i].x==-0?0:verts[i].x);
1820 yStr =
"y"+
ofToString(verts[i].y==-0?0:verts[i].y);
1821 zStr =
"z"+
ofToString(verts[i].z==-0?0:verts[i].z);
1822 std::string vstring = xStr+yStr+zStr;
1823 if(vertHash.find(vstring) == vertHash.end()) {
1824 for(
ofIndexType j = 0; j < triangles.size(); j++) {
1826 if(verts[i].x == triangles[j].getVertex(k).x) {
1827 if(verts[i].y == triangles[j].getVertex(k).y) {
1828 if(verts[i].z == triangles[j].getVertex(k).z) {
1829 vertHash[vstring].push_back( j );
1848 for(
ofIndexType j = 0; j < triangles.size(); j++) {
1850 vert = triangles[j].getVertex(k);
1855 std::string vstring = xStr+yStr+zStr;
1857 normal = {0.f,0.f,0.f};
1858 if(vertHash.find(vstring) != vertHash.end()) {
1859 for(
ofIndexType i = 0; i < vertHash[vstring].size(); i++) {
1860 auto f1 = triangles[j].getFaceNormal();
1861 auto f2 = triangles[vertHash[vstring][i]].getFaceNormal();
1862 if(glm::dot(
toGlm(f1),
toGlm(f2)) >= angleCos ) {
1868 normal /= numNormals;
1870 triangles[j].setNormal(k, normal);
1876 setFromTriangles( triangles );
1882template<
class V,
class N,
class C,
class T>
1887 auto indices = getIndices();
1888 auto verts = getVertices();
1889 auto texCoords = getTexCoords();
1890 auto colors = getColors();
1903 auto e1 = verts[indexCurr] - verts[indexNext1];
1904 auto e2 = verts[indexNext2] - verts[indexNext1];
1905 normal = glm::normalize(glm::cross(e1, e2));
1911 if(indexCurr < texCoords.size()) {
1912 addTexCoord(texCoords[indexCurr]);
1915 if(indexCurr < verts.size()) {
1916 addVertex(verts[indexCurr]);
1919 if(indexCurr < colors.size()) {
1920 addColor(colors[indexCurr]);
1930template<
class V,
class N,
class C,
class T>
1931ofMesh_<V,N,C,T> ofMesh_<V,N,C,T>::plane(
float width,
float height,
int columns,
int rows,
ofPrimitiveMode mode ) {
1935 ofLogWarning(
"ofMesh") <<
"ofGetPlaneMesh(): primtive mode " << mode <<
" not supported, setting to OF_PRIMITIVE_TRIANGLES";
1946 float halfW =
width * 0.5f;
1947 float halfH =
height * 0.5f;
1950 for(
int iy = 0; iy != rows; iy++) {
1951 for(
int ix = 0; ix != columns; ix++) {
1954 texcoord.x = ((float)ix/((
float)columns-1));
1955 texcoord.y = 1.f - ((float)iy/((
float)rows-1));
1957 vert.x = texcoord.x *
width - halfW;
1958 vert.y = -(texcoord.y-1) *
height - halfH;
1966 for(
int y = 0; y < rows-1; y++) {
1969 for(
int x = 0; x < columns; x++) {
1970 mesh.
addIndex( (y) * columns + x );
1971 mesh.
addIndex( (y+1) * columns + x);
1974 for(
int x = columns-1; x >0; x--) {
1975 mesh.
addIndex( (y+1) * columns + x );
1976 mesh.
addIndex( y * columns + x-1 );
1984 for(
int y = 0; y < rows-1; y++) {
1985 for(
int x = 0; x < columns-1; x++) {
1993 mesh.
addIndex((y+1)*columns + x+1);
2005template<
class V,
class N,
class C,
class T>
2010 float doubleRes = res*2.f;
2011 float polarInc = glm::pi<float>()/(res);
2012 float azimInc = glm::two_pi<float>()/(doubleRes);
2022 for(
float i = 0; i < res+1; i++) {
2024 float tr = sin( glm::pi<float>()-i * polarInc );
2025 float ny = cos( glm::pi<float>()-i * polarInc );
2027 tcoord.y = 1.f - (i / res);
2029 for(
float j = 0; j <= doubleRes; j++) {
2031 float nx = tr * sin(j * azimInc);
2032 float nz = tr * cos(j * azimInc);
2034 tcoord.x = j / (doubleRes);
2036 vert = {nx, ny, nz};
2044 int nr = doubleRes+1;
2049 for(
float iy = 0; iy < res; iy++) {
2050 for(
float ix = 0; ix < doubleRes; ix++) {
2054 index1 = (iy+0) * (nr) + (ix+0);
2055 index2 = (iy+0) * (nr) + (ix+1);
2056 index3 = (iy+1) * (nr) + (ix+0);
2065 index1 = (iy+0) * (nr) + (ix+1);
2066 index2 = (iy+1) * (nr) + (ix+1);
2067 index3 = (iy+1) * (nr) + (ix+0);
2078 for(
int y = 0; y < res; y++) {
2079 for(
int x = 0; x <= doubleRes; x++) {
2121template<
class V,
class N,
class C,
class T>
2123 auto mesh = icosphere(radius, 0);
2133template<
class V,
class N,
class C,
class T>
2138 const float sqrt5 = sqrt(5.0f);
2139 const float phi = (1.0f + sqrt5) * 0.5f;
2140 const float invnorm = 1/sqrt(phi*phi+1);
2142 sphere.
addVertex(invnorm * V(-1, phi, 0));
2143 sphere.
addVertex(invnorm * V( 1, phi, 0));
2144 sphere.
addVertex(invnorm * V(0, 1, -phi));
2145 sphere.
addVertex(invnorm * V(0, 1, phi));
2146 sphere.
addVertex(invnorm * V(-phi,0, -1));
2147 sphere.
addVertex(invnorm * V(-phi,0, 1));
2148 sphere.
addVertex(invnorm * V( phi,0, -1));
2149 sphere.
addVertex(invnorm * V( phi,0, 1));
2150 sphere.
addVertex(invnorm * V(0, -1, -phi));
2151 sphere.
addVertex(invnorm * V(0, -1, phi));
2152 sphere.
addVertex(invnorm * V(-1, -phi,0));
2153 sphere.
addVertex(invnorm * V( 1, -phi,0));
2179 sphere.
addTriangle(firstFaces[i], firstFaces[i+1], firstFaces[i+2]);
2188 for (
ofIndexType iteration = 0; iteration < iterations; iteration++)
2191 std::vector<ofIndexType> newFaces;
2194 auto i1 = faces[i*3];
2195 auto i2 = faces[i*3+1];
2196 auto i3 = faces[i*3+2];
2197 auto i12 = vertices.size();
2200 auto v1 = vertices[i1];
2201 auto v2 = vertices[i2];
2202 auto v3 = vertices[i3];
2204 vertices.push_back(glm::normalize(
toGlm(v1+v2)));
2205 vertices.push_back(glm::normalize(
toGlm(v2+v3)));
2206 vertices.push_back(glm::normalize(
toGlm(v1+v3)));
2208 newFaces.push_back(i1);
2209 newFaces.push_back(i12);
2210 newFaces.push_back(i13);
2211 newFaces.push_back(i2);
2212 newFaces.push_back(i23);
2213 newFaces.push_back(i12);
2214 newFaces.push_back(i3);
2215 newFaces.push_back(i13);
2216 newFaces.push_back(i23);
2217 newFaces.push_back(i12);
2218 newFaces.push_back(i23);
2219 newFaces.push_back(i13);
2221 faces.swap(newFaces);
2225 std::vector<T> texCoords;
2228 const auto& vec = vertices[i];
2230 float r0 = sqrtf(vec.x*vec.x+vec.z*vec.z);
2232 alpha = atan2f(vec.z,vec.x);
2233 u = alpha/glm::two_pi<float>()+.5f;
2234 v = atan2f(vec.y, r0)/glm::pi<float>() + .5f;
2238 texCoords.push_back(T(1.0-u,1.f-v));
2243 std::vector<ofIndexType> indexToSplit;
2247 T& t0 = texCoords[faces[i*3+0]];
2248 T& t1 = texCoords[faces[i*3+1]];
2249 T& t2 = texCoords[faces[i*3+2]];
2251 if (std::abs(t2.x-t0.x)>0.5)
2254 indexToSplit.push_back(faces[i*3]);
2256 indexToSplit.push_back(faces[i*3+2]);
2258 if (std::abs(t1.x-t0.x)>0.5)
2261 indexToSplit.push_back(faces[i*3]);
2263 indexToSplit.push_back(faces[i*3+1]);
2265 if (std::abs(t2.x-t1.x)>0.5)
2268 indexToSplit.push_back(faces[i*3+1]);
2270 indexToSplit.push_back(faces[i*3+2]);
2279 V v = vertices[index];
2280 T t = texCoords[index] + T(1.f, 0.f);
2281 vertices.push_back(v);
2282 texCoords.push_back(t);
2287 if (faces[j]==index)
2291 if ((texCoords[index1].x>0.5) || (texCoords[index2].x>0.5))
2293 faces[j] = newIndex;
2304 std::swap(faces[i+1], faces[i+2]);
2310 for(
ofIndexType i = 0; i < vertices.size(); i++ ) {
2311 vertices[i] *= radius;
2327template<
class V,
class N,
class C,
class T>
2328ofMesh_<V,N,C,T> ofMesh_<V,N,C,T>::cylinder(
float radius,
float height,
int radiusSegments,
int heightSegments,
int numCapSegments,
bool bCapped,
ofPrimitiveMode mode ) {
2335 radiusSegments = radiusSegments+1;
2336 int capSegs = numCapSegments;
2337 capSegs = capSegs+1;
2338 heightSegments = heightSegments+1;
2339 if(heightSegments < 2) heightSegments = 2;
2340 if( capSegs < 2 ) bCapped =
false;
2341 if(!bCapped) capSegs=1;
2343 float angleIncRadius = -1 * (glm::two_pi<float>()/((float)radiusSegments-1.f));
2344 float heightInc =
height/((float)heightSegments-1.f);
2345 float halfH =
height*.5f;
2351 glm::vec3 up(0,1,0);
2353 std::size_t vertOffset = 0;
2355 float maxTexY = heightSegments-1.f;
2357 maxTexY += (capSegs*2)-2.f;
2359 float maxTexYNormalized = (capSegs-1.f) / maxTexY;
2362 if(bCapped && capSegs > 0) {
2363 normal = {0.f, -1.f, 0.f};
2364 for(
int iy = 0; iy < capSegs; iy++) {
2365 for(
int ix = 0; ix < radiusSegments; ix++) {
2366 newRad =
ofMap((
float)iy, 0, capSegs-1, 0.0, radius);
2367 vert.x = cos((
float)ix*angleIncRadius) * newRad;
2368 vert.z = sin((
float)ix*angleIncRadius) * newRad;
2371 tcoord.x = (float)ix/((
float)radiusSegments-1.f);
2372 tcoord.y = 1.f -
ofMap(iy, 0, capSegs-1, 0, maxTexYNormalized);
2381 for(
int y = 0; y < capSegs-1; y++) {
2382 for(
int x = 0; x < radiusSegments-1; x++) {
2385 mesh.
addIndex( (y)*radiusSegments + x + vertOffset );
2386 mesh.
addIndex( (y)*radiusSegments + x+1 + vertOffset);
2387 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2391 mesh.
addIndex( (y)*radiusSegments + x+1 + vertOffset);
2392 mesh.
addIndex( (y+1)*radiusSegments + x+1 + vertOffset);
2393 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2397 for(
int y = 0; y < capSegs-1; y++) {
2398 for(
int x = 0; x < radiusSegments; x++) {
2399 mesh.
addIndex( (y)*radiusSegments + x + vertOffset );
2400 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2410 float minTexYNormalized = 0;
2411 if(bCapped) minTexYNormalized = maxTexYNormalized;
2412 maxTexYNormalized = 1.f;
2413 if(bCapped) maxTexYNormalized = (heightSegments) / maxTexY;
2416 for(
int iy = 0; iy < heightSegments; iy++) {
2417 normal = {1.f, 0.f, 0.f};
2418 for(
int ix = 0; ix < radiusSegments; ix++) {
2421 vert.x = cos(ix*angleIncRadius) * radius;
2422 vert.y = heightInc*float(iy) - halfH;
2423 vert.z = sin(ix*angleIncRadius) * radius;
2425 tcoord.x = float(ix)/(float(radiusSegments)-1.f);
2426 tcoord.y = 1.f -
ofMap(iy, 0, heightSegments-1, minTexYNormalized, maxTexYNormalized );
2432 normal = glm::rotate(
toGlm(normal), -angleIncRadius, up);
2438 for(
int y = 0; y < heightSegments-1; y++) {
2439 for(
int x = 0; x < radiusSegments-1; x++) {
2441 mesh.
addIndex( (y)*radiusSegments + x + vertOffset);
2442 mesh.
addIndex( (y)*radiusSegments + x+1 + vertOffset );
2443 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset );
2446 mesh.
addIndex( (y)*radiusSegments + x+1 + vertOffset );
2447 mesh.
addIndex( (y+1)*radiusSegments + x+1 + vertOffset );
2448 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset );
2452 for(
int y = 0; y < heightSegments-1; y++) {
2453 for(
int x = 0; x < radiusSegments; x++) {
2454 mesh.
addIndex( (y)*radiusSegments + x + vertOffset );
2455 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset );
2463 if(bCapped && capSegs > 0) {
2464 minTexYNormalized = maxTexYNormalized;
2465 maxTexYNormalized = 1.f;
2467 normal = {0.f, 1.f, 0.f};
2468 for(
int iy = 0; iy < capSegs; iy++) {
2469 for(
int ix = 0; ix < radiusSegments; ix++) {
2470 newRad =
ofMap((
float)iy, 0, capSegs-1, radius, 0.0);
2471 vert.x = cos((
float)ix*angleIncRadius) * newRad;
2472 vert.z = sin((
float)ix*angleIncRadius) * newRad;
2475 tcoord.x = (float)ix/((
float)radiusSegments-1.f);
2476 tcoord.y = 1.f -
ofMap(iy, 0, capSegs-1, minTexYNormalized, maxTexYNormalized);
2485 for(
int y = 0; y < capSegs-1; y++) {
2486 for(
int x = 0; x < radiusSegments-1; x++) {
2488 mesh.
addIndex( (y)*radiusSegments + x + vertOffset );
2489 mesh.
addIndex( (y)*radiusSegments + x+1 + vertOffset);
2490 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2492 if(y < capSegs -1 && capSegs > 2) {
2494 mesh.
addIndex( (y)*radiusSegments + x+1 + vertOffset);
2495 mesh.
addIndex( (y+1)*radiusSegments + x+1 + vertOffset);
2496 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2501 for(
int y = 0; y < capSegs-1; y++) {
2502 for(
int x = 0; x < radiusSegments; x++) {
2503 mesh.
addIndex( (y)*radiusSegments + x + vertOffset );
2504 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2520template<
class V,
class N,
class C,
class T>
2521ofMesh_<V,N,C,T> ofMesh_<V,N,C,T>::cone(
float radius,
float height,
int radiusSegments,
int heightSegments,
int capSegments,
ofPrimitiveMode mode ) {
2528 radiusSegments = radiusSegments+1;
2529 capSegments = capSegments+1;
2530 heightSegments = heightSegments+1;
2531 if(heightSegments < 2) heightSegments = 2;
2532 int capSegs = capSegments;
2538 float angleIncRadius = -1.f * ((glm::two_pi<float>()/((float)radiusSegments-1.f)));
2539 float heightInc =
height/((float)heightSegments-1);
2540 float halfH =
height*.5f;
2546 glm::vec3 up(0,1,0);
2548 std::size_t vertOffset = 0;
2550 float maxTexY = heightSegments-1.f;
2552 maxTexY += capSegs-1.f;
2555 V startVec(0, -halfH-1.f, 0);
2558 for(
int iy = 0; iy < heightSegments; iy++) {
2559 for(
int ix = 0; ix < radiusSegments; ix++) {
2561 newRad =
ofMap((
float)iy, 0, heightSegments-1, 0.0, radius);
2562 vert.x = cos((
float)ix*angleIncRadius) * newRad;
2563 vert.y = heightInc*((float)iy) - halfH;
2564 vert.z = sin((
float)ix*angleIncRadius) * newRad;
2566 tcoord.x = (float)ix/((
float)radiusSegments-1.f);
2567 tcoord.y = 1.f - (float)iy/((
float)maxTexY);
2574 vert.x = cos((
float)ix*angleIncRadius) * newRad;
2575 vert.y = heightInc*((float)iy) - halfH;
2576 vert.z = sin((
float)ix*angleIncRadius) * newRad;
2579 auto diff =
toGlm(vert - startVec);
2580 auto crossed = glm::cross(up,
toGlm(vert));
2581 normal = glm::cross(crossed, diff);
2588 for(
int y = 0; y < heightSegments-1; y++) {
2589 for(
int x = 0; x < radiusSegments-1; x++) {
2592 mesh.
addIndex( (y)*radiusSegments + x );
2593 mesh.
addIndex( (y)*radiusSegments + x+1 );
2594 mesh.
addIndex( (y+1)*radiusSegments + x );
2598 mesh.
addIndex( (y)*radiusSegments + x+1 );
2599 mesh.
addIndex( (y+1)*radiusSegments + x+1 );
2600 mesh.
addIndex( (y+1)*radiusSegments + x );
2604 for(
int y = 0; y < heightSegments-1; y++) {
2605 for(
int x = 0; x < radiusSegments; x++) {
2606 mesh.
addIndex( (y)*radiusSegments + x );
2607 mesh.
addIndex( (y+1)*radiusSegments + x );
2613 float maxTexYNormalized = (heightSegments-1.f) / maxTexY;
2616 normal= {0.f,1.f,0.f};
2617 for(
int iy = 0; iy < capSegs; iy++) {
2618 for(
int ix = 0; ix < radiusSegments; ix++) {
2619 newRad =
ofMap((
float)iy, 0, capSegs-1, radius, 0.0);
2620 vert.x = cos((
float)ix*angleIncRadius) * newRad;
2621 vert.z = sin((
float)ix*angleIncRadius) * newRad;
2624 tcoord.x = (float)ix/((
float)radiusSegments-1.f);
2625 tcoord.y = 1.f -
ofMap(iy, 0, capSegs-1, maxTexYNormalized, 1.f);
2635 for(
int y = 0; y < capSegs-1; y++) {
2636 for(
int x = 0; x < radiusSegments-1; x++) {
2638 mesh.
addIndex( (y)*radiusSegments + x + vertOffset );
2639 mesh.
addIndex( (y)*radiusSegments + x+1 + vertOffset);
2640 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2644 mesh.
addIndex( (y)*radiusSegments + x+1 + vertOffset);
2645 mesh.
addIndex( (y+1)*radiusSegments + x+1 + vertOffset);
2646 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2653 for(
int y = 0; y < capSegs-1; y++) {
2654 for(
int x = 0; x < radiusSegments; x++) {
2655 mesh.
addIndex( (y)*radiusSegments + x + vertOffset );
2656 mesh.
addIndex( (y+1)*radiusSegments + x + vertOffset);
2670template<
class V,
class N,
class C,
class T>
2671ofMesh_<V,N,C,T> ofMesh_<V,N,C,T>::box(
float width,
float height,
float depth,
int resX,
int resY,
int resZ ) {
2680 if( resX < 2 ) resX = 0;
2681 if( resY < 2 ) resY = 0;
2682 if( resZ < 2 ) resZ = 0;
2685 float halfW =
width * .5f;
2686 float halfH =
height * .5f;
2687 float halfD = depth * .5f;
2692 std::size_t vertOffset = 0;
2697 normal = {0.f, 0.f, 1.f};
2699 for(
int iy = 0; iy < resY; iy++) {
2700 for(
int ix = 0; ix < resX; ix++) {
2703 texcoord.x = ((float)ix/((
float)resX-1.f));
2704 texcoord.y = 1.f - ((float)iy/((
float)resY-1.f));
2706 vert.x = texcoord.x *
width - halfW;
2707 vert.y = -(texcoord.y-1.f) *
height - halfH;
2716 for(
int y = 0; y < resY-1; y++) {
2717 for(
int x = 0; x < resX-1; x++) {
2719 mesh.
addIndex((y)*resX + x + vertOffset);
2720 mesh.
addIndex((y+1)*resX + x + vertOffset);
2721 mesh.
addIndex((y)*resX + x+1 + vertOffset);
2724 mesh.
addIndex((y)*resX + x+1 + vertOffset);
2725 mesh.
addIndex((y+1)*resX + x + vertOffset);
2726 mesh.
addIndex((y+1)*resX + x+1 + vertOffset);
2734 normal = {1.f, 0.f, 0.f};
2736 for(
int iy = 0; iy < resY; iy++) {
2737 for(
int ix = 0; ix < resZ; ix++) {
2740 texcoord.x = ((float)ix/((
float)resZ-1.f));
2741 texcoord.y = 1.f - ((float)iy/((
float)resY-1.f));
2745 vert.y = -(texcoord.y-1.f) *
height - halfH;
2746 vert.z = texcoord.x * -depth + halfD;
2754 for(
int y = 0; y < resY-1; y++) {
2755 for(
int x = 0; x < resZ-1; x++) {
2757 mesh.
addIndex((y)*resZ + x + vertOffset);
2758 mesh.
addIndex((y+1)*resZ + x + vertOffset);
2759 mesh.
addIndex((y)*resZ + x+1 + vertOffset);
2762 mesh.
addIndex((y)*resZ + x+1 + vertOffset);
2763 mesh.
addIndex((y+1)*resZ + x + vertOffset);
2764 mesh.
addIndex((y+1)*resZ + x+1 + vertOffset);
2771 normal = {-1.f, 0.f, 0.f};
2773 for(
int iy = 0; iy < resY; iy++) {
2774 for(
int ix = 0; ix < resZ; ix++) {
2777 texcoord.x = ((float)ix/((
float)resZ-1.f));
2778 texcoord.y = 1.f-((float)iy/((
float)resY-1.f));
2782 vert.y = -(texcoord.y-1.f) *
height - halfH;
2783 vert.z = texcoord.x * depth - halfD;
2791 for(
int y = 0; y < resY-1; y++) {
2792 for(
int x = 0; x < resZ-1; x++) {
2794 mesh.
addIndex((y)*resZ + x + vertOffset);
2795 mesh.
addIndex((y+1)*resZ + x + vertOffset);
2796 mesh.
addIndex((y)*resZ + x+1 + vertOffset);
2799 mesh.
addIndex((y)*resZ + x+1 + vertOffset);
2800 mesh.
addIndex((y+1)*resZ + x + vertOffset);
2801 mesh.
addIndex((y+1)*resZ + x+1 + vertOffset);
2809 normal = {0.f, 0.f, -1.f};
2811 for(
int iy = 0; iy < resY; iy++) {
2812 for(
int ix = 0; ix < resX; ix++) {
2815 texcoord.x = ((float)ix/((
float)resX-1.f));
2816 texcoord.y = 1.f-((float)iy/((
float)resY-1.f));
2818 vert.x = texcoord.x * -
width + halfW;
2819 vert.y = -(texcoord.y-1.f) *
height - halfH;
2828 for(
int y = 0; y < resY-1; y++) {
2829 for(
int x = 0; x < resX-1; x++) {
2831 mesh.
addIndex((y)*resX + x + vertOffset);
2832 mesh.
addIndex((y+1)*resX + x + vertOffset);
2833 mesh.
addIndex((y)*resX + x+1 + vertOffset);
2836 mesh.
addIndex((y)*resX + x+1 + vertOffset);
2837 mesh.
addIndex((y+1)*resX + x + vertOffset);
2838 mesh.
addIndex((y+1)*resX + x+1 + vertOffset);
2846 normal = {0.f, -1.f, 0.f};
2848 for(
int iy = 0; iy < resZ; iy++) {
2849 for(
int ix = 0; ix < resX; ix++) {
2852 texcoord.x = ((float)ix/((
float)resX-1.f));
2853 texcoord.y = 1.f-((float)iy/((
float)resZ-1.f));
2855 vert.x = texcoord.x *
width - halfW;
2858 vert.z = texcoord.y * depth - halfD;
2866 for(
int y = 0; y < resZ-1; y++) {
2867 for(
int x = 0; x < resX-1; x++) {
2869 mesh.
addIndex((y)*resX + x + vertOffset);
2870 mesh.
addIndex((y)*resX + x+1 + vertOffset);
2871 mesh.
addIndex((y+1)*resX + x + vertOffset);
2874 mesh.
addIndex((y)*resX + x+1 + vertOffset);
2875 mesh.
addIndex((y+1)*resX + x+1 + vertOffset);
2876 mesh.
addIndex((y+1)*resX + x + vertOffset);
2884 normal = {0.f, 1.f, 0.f};
2886 for(
int iy = 0; iy < resZ; iy++) {
2887 for(
int ix = 0; ix < resX; ix++) {
2890 texcoord.x = ((float)ix/((
float)resX-1.f));
2891 texcoord.y = 1.f-((float)iy/((
float)resZ-1.f));
2893 vert.x = texcoord.x *
width - halfW;
2896 vert.z = texcoord.y * -depth + halfD;
2904 for(
int y = 0; y < resZ-1; y++) {
2905 for(
int x = 0; x < resX-1; x++) {
2907 mesh.
addIndex((y)*resX + x + vertOffset);
2908 mesh.
addIndex((y)*resX + x+1 + vertOffset);
2909 mesh.
addIndex((y+1)*resX + x + vertOffset);
2912 mesh.
addIndex((y)*resX + x+1 + vertOffset);
2913 mesh.
addIndex((y+1)*resX + x+1 + vertOffset);
2914 mesh.
addIndex((y+1)*resX + x + vertOffset);
2926template<
class V,
class N,
class C,
class T>
2959template<
class V,
class N,
class C,
class T>
2963,bHasTexcoords(false)
2964,bFaceNormalDirty(false)
2969template<
class V,
class N,
class C,
class T>
2971 if(bFaceNormalDirty) calculateFaceNormal();
2976template<
class V,
class N,
class C,
class T>
2980 u =
toGlm(vertices[1]-vertices[0]);
2981 v =
toGlm(vertices[2]-vertices[0]);
2983 faceNormal = glm::cross(u, v);
2984 faceNormal = glm::normalize(
toGlm(faceNormal));
2985 bFaceNormalDirty =
false;
2989template<
class V,
class N,
class C,
class T>
2991 vertices[index] = v;
2992 bFaceNormalDirty =
true;
2996template<
class V,
class N,
class C,
class T>
2998 return vertices[index];
3002template<
class V,
class N,
class C,
class T>
3009template<
class V,
class N,
class C,
class T>
3011 return normals[ index ];
3015template<
class V,
class N,
class C,
class T>
3017 colors[index] = color;
3022template<
class V,
class N,
class C,
class T>
3024 return colors[index];
3028template<
class V,
class N,
class C,
class T>
3030 texCoords[index] = tCoord;
3031 bHasTexcoords =
true;
3035template<
class V,
class N,
class C,
class T>
3037 return texCoords[index];
3041template<
class V,
class N,
class C,
class T>
3043 bHasColors = bColors;
3047template<
class V,
class N,
class C,
class T>
3049 bHasNormals = bNormals;
3053template<
class V,
class N,
class C,
class T>
3055 bHasTexcoords = bTexcoords;
3059template<
class V,
class N,
class C,
class T>
3065template<
class V,
class N,
class C,
class T>
3071template<
class V,
class N,
class C,
class T>
3073 return bHasTexcoords;
Definition ofFileUtils.h:15
Lines getLines()
Definition ofFileUtils.cpp:432
PixelType g
The green color component.
Definition ofColor.h:90
PixelType r
The red color component.
Definition ofColor.h:89
PixelType a
The alpha color component.
Definition ofColor.h:92
PixelType b
The blue color component.
Definition ofColor.h:91
Definition ofFileUtils.h:472
@ ReadOnly
Definition ofFileUtils.h:479
@ WriteOnly
Definition ofFileUtils.h:480
Derived log class for easy error logging.
Definition ofLog.h:606
Derived log class for easy warning logging.
Definition ofLog.h:585
Represents a set of vertices in 3D spaces with normals, colors, and texture coordinates at those poin...
Definition ofMesh.h:78
void setColorForIndices(ofIndexType startIndex, ofIndexType endIndex, C color)
Definition ofMesh.inl:1453
std::size_t getNumVertices() const
Definition ofMesh.inl:522
virtual void enableIndices()
Enable mesh indices. Use disableIndices() to turn indices off. Indices are enabled by default when th...
Definition ofMesh.inl:992
void clearNormals()
Remove all the normals.
Definition ofMesh.inl:887
void removeVertices(ofIndexType startIndex, ofIndexType endIndex)
Removes the vertices at the startIndex in the vector and the endindex specified.
Definition ofMesh.inl:365
void setMode(ofPrimitiveMode mode)
Allows you to set the ofPrimitiveMode. The available modes are OF_PRIMITIVE_TRIANGLES,...
Definition ofMesh.inl:803
void addTriangle(ofIndexType index1, ofIndexType index2, ofIndexType index3)
Adding a triangle means using three of the vertices that have already been added to create a triangle...
Definition ofMesh.inl:343
virtual void enableTextures()
Enable mesh textures. Use disableTextures() to turn textures off. Textures are enabled by default whe...
Definition ofMesh.inl:976
N getNormal(ofIndexType i) const
\returns the normal at the index in the normals vector.
Definition ofMesh.inl:498
T * getTexCoordsPointer()
Definition ofMesh.inl:604
void removeIndices(ofIndexType startIndex, ofIndexType endIndex)
Definition ofMesh.inl:465
static ofMesh_ sphere(float radius, int res=12, ofPrimitiveMode mode=OF_PRIMITIVE_TRIANGLE_STRIP)
Definition ofMesh.inl:2006
virtual void enableNormals()
Enable mesh normals. Use disableNormals() to turn normals off. Normals are enabled by default when th...
Definition ofMesh.inl:984
void addIndex(ofIndexType i)
Definition ofMesh.inl:313
void drawFaces() const
This draws the mesh as faces, meaning that you'll have a collection of faces.
Definition ofMesh.inl:943
bool hasIndices() const
/returns Whether the mesh has any indices assigned to it.
Definition ofMesh.inl:174
void removeNormal(ofIndexType index)
Remove a normal.
Definition ofMesh.inl:379
bool hasTexCoords() const
/returns Whether the mesh has any textures assigned to it.
Definition ofMesh.inl:166
virtual bool usingNormals() const
Definition ofMesh.inl:1048
void addColors(const std::vector< C > &cols)
This adds colors using a reference to a vector of ofColors. For each color in the vector,...
Definition ofMesh.inl:224
bool haveColorsChanged()
Definition ofMesh.inl:89
void setIndex(ofIndexType index, ofIndexType val)
This sets the index at i.
Definition ofMesh.inl:853
static ofMesh_ plane(float width, float height, int columns=2, int rows=2, ofPrimitiveMode mode=OF_PRIMITIVE_TRIANGLE_STRIP)
Definition ofMesh.inl:1931
std::size_t getNumNormals() const
This will tell you how many normals are contained in the mesh.
Definition ofMesh.inl:538
ofIndexType getIndex(ofIndexType i) const
Definition ofMesh.inl:305
virtual void enableColors()
Enable mesh colors. Use disableColors() to turn colors off. Colors are enabled by default when they a...
Definition ofMesh.inl:968
static ofMesh_ cone(float radius, float height, int radiusSegments=12, int heightSegments=6, int capSegments=2, ofPrimitiveMode mode=OF_PRIMITIVE_TRIANGLE_STRIP)
A helper method that returns a cone made of triangles. The resolution settings for the radius,...
Definition ofMesh.inl:2521
bool haveVertsChanged()
Definition ofMesh.inl:76
void addNormal(const N &n)
Add a normal to the mesh as a 3D vector, typically perpendicular to the plane of the face....
Definition ofMesh.inl:244
void clearTexCoords()
Clear all the texture coordinates.
Definition ofMesh.inl:907
ofMesh_()
This creates the mesh, using OF_PRIMITIVE_TRIANGLES without any initial vertices.
Definition ofMesh.inl:17
bool hasNormals() const
/returnsWhether the mesh has any normals.
Definition ofMesh.inl:158
void clearVertices()
Removes all the vertices.
Definition ofMesh.inl:878
void draw() const
This draws the mesh using its primitive type, meaning that if you set them up to be triangles,...
Definition ofMesh.inl:951
bool hasColors() const
/returns Whether the mesh has any colors.
Definition ofMesh.inl:150
void mergeDuplicateVertices()
Definition ofMesh.inl:1538
void setupIndicesAuto()
Allow you to set up the indices automatically when you add a vertex.
Definition ofMesh.inl:863
void load(const of::filesystem::path &path)
Loads a mesh from a file located at the provided path into the mesh. This will replace any existing d...
Definition ofMesh.inl:1091
void append(const ofMesh_ &mesh)
Add the vertices, normals, texture coordinates and indices of one mesh onto another mesh....
Definition ofMesh.inl:1065
void removeNormals(ofIndexType startIndex, ofIndexType endIndex)
Remove normal's from index to end index from normals vector.
Definition ofMesh.inl:390
void addTexCoords(const std::vector< T > &tCoords)
Add a vector of texture coordinates to a mesh, allowing you to push out many at once rather than addi...
Definition ofMesh.inl:285
std::vector< ofIndexType > & getIndices()
Use this if you plan to change the indices as part of this call as it will force a reset of the cache...
Definition ofMesh.inl:691
V * getVerticesPointer()
Definition ofMesh.inl:580
bool haveTexCoordsChanged()
Definition ofMesh.inl:115
std::vector< C > & getColors()
Definition ofMesh.inl:667
virtual void disableNormals()
Disable mesh normals. Use enableNormals() to turn normals back on.
Definition ofMesh.inl:1016
std::size_t getNumTexCoords() const
This will tell you how many texture coordinates are contained in the mesh.
Definition ofMesh.inl:546
void setColor(ofIndexType index, const C &c)
Set the color at the index in the colors vector.
Definition ofMesh.inl:833
void removeColors(ofIndexType startIndex, ofIndexType endIndex)
Remove colors at the index to the end index of the colors vector.
Definition ofMesh.inl:414
const std::vector< ofMeshFace_< V, N, C, T > > & getUniqueFaces() const
Definition ofMesh.inl:1647
void smoothNormals(float angle)
Definition ofMesh.inl:1782
void removeTexCoord(ofIndexType index)
Remove a Vec2f representing the texture coordinate.
Definition ofMesh.inl:428
static ofMesh_ cylinder(float radius, float height, int radiusSegments=12, int heightSegments=6, int numCapSegments=2, bool bCapped=true, ofPrimitiveMode mode=OF_PRIMITIVE_TRIANGLE_STRIP)
A helper method that returns a cylinder made of triangles. The resolution settings for the radius,...
Definition ofMesh.inl:2328
void flatNormals()
Duplicates vertices and updates normals to get a low-poly look.
Definition ofMesh.inl:1883
void removeVertex(ofIndexType index)
Removes the vertex at the index in the vector.
Definition ofMesh.inl:354
virtual void disableIndices()
Disable mesh indices. Use enableIndices() to turn indices back on.
Definition ofMesh.inl:1024
std::size_t getNumIndices() const
This will tell you how many indices are contained in the mesh.
Definition ofMesh.inl:554
V getVertex(ofIndexType i) const
Definition ofMesh.inl:490
ofMeshFace_< V, N, C, T > getFace(ofIndexType faceId) const
Definition ofMesh.inl:1634
virtual bool usingTextures() const
Definition ofMesh.inl:1040
virtual bool usingColors() const
Definition ofMesh.inl:1032
std::vector< V > & getVertices()
Definition ofMesh.inl:659
void clear()
Removes all the vertices, colors, and indices from the mesh.
Definition ofMesh.inl:49
bool hasVertices() const
Definition ofMesh.inl:142
void addTexCoord(const T &t)
Add a Vec2f representing the texture coordinate. Because OF uses ARB textures these are in pixels rat...
Definition ofMesh.inl:274
std::size_t getNumColors() const
Definition ofMesh.inl:530
static ofMesh_ icosahedron(float radius)
Definition ofMesh.inl:2122
void addIndices(const std::vector< ofIndexType > &inds)
This adds a vector of indices.
Definition ofMesh.inl:323
T getTexCoord(ofIndexType i) const
Definition ofMesh.inl:514
virtual void disableTextures()
Disable mesh textures. Use enableTextures() to turn textures back on.
Definition ofMesh.inl:1008
virtual void disableColors()
Disable mesh colors. Use enableColors() to turn colors back on.
Definition ofMesh.inl:1000
void removeColor(ofIndexType index)
Remove a color at the index in the colors vector.
Definition ofMesh.inl:403
void addVertex(const V &v)
Add a new vertex at the end of the current list of vertices. It is important to remember that the ord...
Definition ofMesh.inl:184
void setVertex(ofIndexType index, const V &v)
Definition ofMesh.inl:812
std::vector< N > & getNormals()
Definition ofMesh.inl:675
std::vector< N > getFaceNormals(bool perVetex=false) const
Get normals for each face As a default it only calculates the normal for the face as a whole but by s...
Definition ofMesh.inl:1690
void removeIndex(ofIndexType index)
Removes an index.
Definition ofMesh.inl:454
N * getNormalsPointer()
Definition ofMesh.inl:596
ofPrimitiveMode getMode() const
\returns the primitive mode that the mesh is using.
Definition ofMesh.inl:482
bool haveNormalsChanged()
Definition ofMesh.inl:102
void save(const of::filesystem::path &path, bool useBinary=false) const
Saves the mesh at the passed path in the PLY Format.
Definition ofMesh.inl:1331
ofIndexType * getIndexPointer()
Definition ofMesh.inl:612
void setTexCoord(ofIndexType index, const T &t)
Definition ofMesh.inl:843
void removeTexCoords(ofIndexType startIndex, ofIndexType endIndex)
Definition ofMesh.inl:439
static ofMesh_ icosphere(float radius, std::size_t iterations=2)
Definition ofMesh.inl:2134
C getColor(ofIndexType i) const
Get the color at the index in the colors vector.
Definition ofMesh.inl:506
void addNormals(const std::vector< N > &norms)
Add a vector of normals to a mesh, allowing you to push out many normals at once rather than adding o...
Definition ofMesh.inl:254
void setNormal(ofIndexType index, const N &n)
Definition ofMesh.inl:823
C * getColorsPointer()
Definition ofMesh.inl:588
void clearIndices()
Remove all the indices of the mesh. This means that your mesh will be a point cloud.
Definition ofMesh.inl:917
void addColor(const C &c)
This adds a color to the mesh, the color will be associated with the vertex in the same position.
Definition ofMesh.inl:214
bool haveIndicesChanged()
Definition ofMesh.inl:128
std::vector< T > & getTexCoords()
Get a vector representing the texture coordinates of the mesh Because OF uses ARB textures these are ...
Definition ofMesh.inl:683
V getCentroid() const
Definition ofMesh.inl:784
void setFromTriangles(const std::vector< ofMeshFace_< V, N, C, T > > &tris, bool bUseFaceNormal=false)
Definition ofMesh.inl:1725
void drawWireframe() const
This draws the mesh as GL_LINES, meaning that you'll have a wireframe.
Definition ofMesh.inl:935
virtual bool usingIndices() const
Definition ofMesh.inl:1056
void addVertices(const std::vector< V > &verts)
Add a vector of vertices to a mesh, allowing you to push out many at once rather than adding one at a...
Definition ofMesh.inl:194
ofMesh_< V, N, C, T > getMeshForIndices(ofIndexType startIndex, ofIndexType endIndex) const
Definition ofMesh.inl:1467
void clearColors()
Clear all the colors.
Definition ofMesh.inl:897
static ofMesh_ axis(float size=1.0)
Returns an ofMesh representing an XYZ coordinate system.
Definition ofMesh.inl:2927
void drawVertices() const
This allows you draw just the vertices, meaning that you'll have a point cloud.
Definition ofMesh.inl:927
static ofMesh_ box(float width, float height, float depth, int resX=2, int resY=2, int resZ=2)
A helper method that returns a box made of triangles. The resolution settings for the width and heigh...
Definition ofMesh.inl:2671
An ofMeshFace_ is a face on one of the ofPrimitive instances. In the ofPrimitive a face consists of 3...
Definition ofMesh.h:680
const V & getVertex(ofIndexType index) const
Definition ofMesh.inl:2997
const N & getFaceNormal() const
Definition ofMesh.inl:2970
bool hasTexcoords() const
Definition ofMesh.inl:3072
const T & getTexCoord(ofIndexType index) const
Definition ofMesh.inl:3036
void setColor(ofIndexType index, const C &color)
Definition ofMesh.inl:3016
void setHasColors(bool bColors)
Definition ofMesh.inl:3042
const C & getColor(ofIndexType index) const
Definition ofMesh.inl:3023
bool hasColors() const
Definition ofMesh.inl:3060
ofMeshFace_()
Definition ofMesh.inl:2960
void setHasNormals(bool bNormals)
Definition ofMesh.inl:3048
void setNormal(ofIndexType index, const N &n)
Definition ofMesh.inl:3003
bool hasNormals() const
Definition ofMesh.inl:3066
void setHasTexcoords(bool bTexcoords)
Definition ofMesh.inl:3054
void setVertex(ofIndexType index, const V &v)
Definition ofMesh.inl:2990
void setTexCoord(ofIndexType index, const T &tCoord)
Definition ofMesh.inl:3029
const N & getNormal(ofIndexType index) const
Definition ofMesh.inl:3010
unsigned int height
Definition ofAppEGLWindow.cpp:125
unsigned int width
Definition ofAppEGLWindow.cpp:124
shared_ptr< ofBaseRenderer > & ofGetCurrentRenderer()
Definition ofAppRunner.cpp:317
TESSindex ofIndexType
Definition ofConstants.h:290
std::string ofToString(const T &)
Convert a value to a string.
Definition ofUtils.h:657
ofPrimitiveMode
Definition ofGraphicsConstants.h:20
@ OF_PRIMITIVE_TRIANGLES
Definition ofGraphicsConstants.h:21
@ OF_PRIMITIVE_TRIANGLE_STRIP
Definition ofGraphicsConstants.h:22
@ OF_PRIMITIVE_LINES
Definition ofGraphicsConstants.h:24
ofPolyRenderMode
Definition ofGraphicsConstants.h:13
@ OF_MESH_WIREFRAME
Definition ofGraphicsConstants.h:15
@ OF_MESH_POINTS
Definition ofGraphicsConstants.h:14
@ OF_MESH_FILL
Definition ofGraphicsConstants.h:16
float ofDegToRad(float degrees)
Convert degrees to radians.
Definition ofMath.cpp:142
float ofMap(float value, float inputMin, float inputMax, float outputMin, float outputMax, bool clamp)
Given a value and an input range, map the value to an output range.
Definition ofMath.cpp:78
const glm::vec2 & toGlm(const ofVec2f &v)
Definition ofVectorMath.h:72
Definition ofFileUtils.h:149
Definition ofFileUtils.h:211
Line end()
Get the last line in the buffer.
Definition ofFileUtils.cpp:411
Line begin()
Get the first line in the buffer.
Definition ofFileUtils.cpp:406