Performance issue with SUFaceCreateSimple


#1

Hi Experts,
I am using the C API writing out sketch up files. say if I have 20,000 triangles and we found the performance is quite slow, my whole small exe runs about 140s and the SUFaceCreateSimple took 96% part of the running time. Is it possible to improve the face creation performance or are there any other alternative manners to create a mesh body with such kind level facets quickly?

Currently it significantly slow down our product’s performance, and the output skp file takes ~2MB which is quite small.

SUFaceCreateSimple..135.986s
SUEntitiesAddFaces..3.28848s


int _tmain(int argc, _TCHAR* argv[])

{
SUModelRef m_model;

SUInitialize();

// Create an empty model
SUSetInvalid(m_model);
SUResult res = SUModelCreate(&m_model);
// It's best to always check the return code from each SU function call.
// Only showing this check once to keep this example short.
if (res != SU_ERROR_NONE)
    return 0;

// Get the entity container of the model
SUEntitiesRef entities = SU_INVALID;
SUModelGetEntities(m_model, &entities);

Timer t1;
t1.StartCounter();
std::vector<SUFaceRef> faces;
int index = 0;
std::vector<SUPoint3D> vertices;
for(int i = 0; i < 20000; i ++)
{
    SUPoint3D p0 = {0, 0, 0};
    SUPoint3D p1 = {i, 10, 0};
    SUPoint3D p2 = {i, 0, 10};
    vertices.push_back(p0);
    vertices.push_back(p1);
    vertices.push_back(p2);


    // Create the face
    SUFaceRef face = SU_INVALID;

    res = SUFaceCreateSimple(&face, &vertices[0], vertices.size());
    assert(res == SU_ERROR_NONE); 

    faces.push_back(face);

    vertices.clear();
}

std::cout << "SUFaceCreateSimple.." <<  t1.GetCounter() / 1000 << std::endl;

t1.StartCounter();
SUEntitiesAddFaces(entities, faces.size(), &faces[0]);
std::cout << "SUEntitiesAddFaces.." <<  t1.GetCounter() / 1000 << std::endl;

// Save the in-memory model to a file
SUModelSaveToFile(m_model, "c:\\new_model.skp");
// Must release the model or there will be memory leaks
SUModelRelease(&m_model);
SUTerminate();
return 0;

}


#2

For bulk creation of faces SUGeometryInput is better suited: http://www.sketchup.com/intl/en/developer/su-api/geometry__input_8h.html

It preps the set of faces you are creating and adds them to the model more efficient than creating them one by one.


#3

So if I have a tessellated face, for simple, a rectangle was tessellated into two triangles.
Do I need create Loop twice and AddFace twice?

  for (size_t tri_index = 0; tri_index < 2; ++tri_index)
{
  // Set up an outer loop input for the face
  SULoopInputRef loop = SU_INVALID;
  SU_CALL(SULoopInputCreate(&loop));
  for (size_t i = 0; i < num_face_vertices; ++i) {
    SU_CALL(SULoopInputAddVertexIndex(loop, tri_index * num_face_vertices + i));
  }
  // Add the face
  size_t face_index = 0;
  SU_CALL(SUGeometryInputAddFace(geom_input, &loop, &face_index));
}

I got crash for SUGeometryInputRelease() and seems related with the Loop vertex index setting, what’s the rule for the index setting in this case? Especially there are 2 or more rectangles?


#4

I’m confused, you say you have a rectangle, but you try to create it as two triangles? You want the end result to be two triangles in SketchUp, or you want it to be one rectangular face?

The exporter examples should demonstrate how you add multiple faces using GeometryInput. Have you looked at them?


#5

Actually what I have is a tessllated surface body(say a simple Cube).
Tesslated results are 12 facets, and I also can know 6 faces and every face having which two facets. Since I found the performance of SUGeometryInputAddFace still quite slow so I am thinking if I could write out 6 faces instead of 12 facets for performance consideration.

I checked the export codes for tessellated faces.
seems it treat every triangle facet as a face in the GeometryInput.
Is it a good practice to merge triangle facets into a larger face to reduce the calling of SUGeometryInputAddFace?
Or the recommend practice is just add facet one by one?

Especially when I call SUGeometryInputAddFace for every facet, I got confused for the loop’s index calculation, and the app crash always at SUGeometryInputRelease after addding the geometryInput into parent entities.


#6

In SketchUp API’s you can only describe the face by it vertices. You cannot define the tessellation itself.
If you want each side of your cube to be treated as one polygon (face) then you must add it as such. If you add each of the triangles individually and SketchUp will treat them as separate faces.
Normally users of SketchUp don’t want the low level tessellation triangles.

Without knowing the context here is hard to advice what to do.


#7

So after I add the created geometryinput item into it’s parent group via SUEntitiesFill, need I release the geometryinput item by //SUGeometryInputRelease(&geoRef)?

In my app this release cause my app crash. and if I comment this line then everything goes right and the model can be exported also.

sw.zip (1.1 MB)
I uploaded the model. when open the model sketchup reported has something minor messed up the model but seems the fix works after I choose Fix Now.


#8

Yes you should release it. We recently added a sample called “TextureMapping” to the SDK package, you might want to look at that.

The model you posted is definitely not right. There are a tremendous number of overlapping faces. Hard to say how this happened without seeing sample code and the original data.

Also, I am surprised that you found SUGeometryInputAddFace is that slow. All it does is a push_back to an std::vector and a delete.