Sdk sample importer

I’m trying to get started with the SDK. I’ve built the sample xml_to_skp importer (64-bit, v140 platform toolset), and dropped it into

C:\Program Files\SketchUp\SketchUp 2017\Importers

…assuming that was the right place.

With the dll in place, sketchup barely gets past the splash screen before dying. Nothing helpful in the log.

The API documentation states “the following C runtime DLLs must be included: msvcp140.dll and msvcr140.dll” - but doesnt say where they can be found or where they should go - with the other dlls in the importers directory?

Even more confusing, instances of msvcp140.dll appear when I search the drive, but not msvcr140.dll
And the ‘alternative’ redistributable package fails to load.

So I’m a bit stuck, any help would be very appreciated.

1 Like

What build configuration did you try?
There is a weakness in the importer/exporter harness in that you cannot use Debug builds along with the released versions of SU.

As for the DLLs, when you write and importer/exporter you don’t need to worry about that. Your importer/exporter will run from SketchUp which will have these distributed and loaded.

They are only needed when using outside the context of SketchUp. In your own application for instance.

1 Like

Rebuilding as Release worked - thanks ThomThom!

Thanks to verifying that worked. We got an issue logged to improve this. First would be to update our SDK example and documentation. But we might want to introduce a new interface in the future.

If you do need to debug your extension, keep it as Release, but configure it to create debug symbols. You might want to keep the original Release config as-is - and instead adjust the Debug instead.

I’ve ported the core of my glTF importer from Ruby into C, and started work this morning on the Sketchup API portion of it. I just ran the importer for the first time on a couple of glTF models - basic faces only, no textures, colours, or even any transforms yet, but the speed, wow! A model that took literally hours to import using the ruby import took less than a minute. I’d guess at this stage that it is fully two magnitudes faster.

That tells me something is seriously wrong with the ruby API implementation!

1 Like

Ruby is interpreted. C is compiled.

You can also greatly slow Ruby code down by creating unnecessary object references, especially inside loops. Or re-creating the same reference inside a loop that should be set once before the loop begins. (At one time there was a large forum thread on optimization [either here or at SCF] that Ruby coders should get good info from.)

I’m aware of that, but in my opinion it is the API as exposed to ruby that has the issue. I can’t use add_polygon because the points being added use unique UV coordinates, and the Ruby API for PolygonMesh.add_point tries to ‘help’ by returning an index from a hash if it finds it has been added already, which is bad behaviour. I also can’t rely on the order that the faces were added when using the PolygonMesh methods.
Hence the only working mechanism to import faces is to use entities.add_face, for each and every face. Then set UV coordinates, material, etc.
Without the add_face call, the code runs quickly - it is only when adding geometry that performance suffers.

By the way, what are you using to create faces in C API? Note that SUFaceCreate SUFaceCreateSimple is bugged, it doesn’t merge entities as it should. (There should be warnings in the docs about this.)

SUGeometryInput is the recommended method of crafting geometry in the C API at this point.

As for the Ruby vs C difference - there are so many things that can lead to the difference. For instance a common pitfall among Ruby extensions is the use of .typename to check the entity type - this perform string comparison which is very slow.

Then you have Ruby’s add_face which isn’t really made for bulk generation. It trigger a re-merge on each call. Which is why Geom::PolygonMesh is faster - but it also have limitations in what you can control. And it have some inefficient method of checking if a point already exist with the same coordinates. (Linear search)

@tt_su

So far I’ve been copying the example provided in the xml_to_skp importer, so using:
SUGeometryInputCreate
SUGeometryInputAddVertex

SULoopInputCreate
SULoopInputAddVertexIndex
SULoopInputEdgeSetHidden
SULoopInputEdgeSetSmooth
SULoopInputEdgeSetSoft
SUGeometryInputAddFace
SUGeometryInputFaceSetFrontMaterial
SUEntitiesFill
SUGeometryInputRelease

in that order.

I’m really pleased with performance so far, and I’ve got texture mapping, basic colours, vertex colours (applying average colour to the face), and the matrix transforms all implemented since yesterday! Next stage is to implement component definitions for those nodes that repeat themselves, and afterwards I will try to find a way to distribute the DLL.

For the ruby code, I can’t use PolygonMesh, as I need to be able to track each face added to apply the UV coordinates, and even if it is a basic colour mesh, I still need to track each face for determining which edges need to be smooth. So that means using add_face.

This is the ruby code that I wrote for the importer, I’m sure a professional developer will be horrified :stuck_out_tongue: but it works. As you note, add_face triggers the remerge, so for massive amounts of geometry it is the reason the import gets progressively slower - some imports taking days to complete. Better add to the 2018 wish-list for a begin-import end-import pair of ruby API functions for turning this off.

i = 0
while i < indices.length
	
	points = []
	normals = []
	pt_array = []
	indice_array = []
	
	n = nil
	j = 0
	while j < 3
		index = indices[i+j]
		indice_array.push(index)
		pt = t_positions[index]
		if normal != nil
			n = normal[index]
			normals.push(n)
		end
		
		points.push(pt)
		
		if(texcoord != nil)
			t = texcoord[index]
			pt_array.push(pt)
			pt_array.push(Geom::Point3d.new(t[0],1.0-t[1],0.0))
		end
		j = j + 1
	end
	
	if colors != nil
		material = add_material(nil, colors[i][0], colors[i][1], colors[i][2], colors[i][3], nil)
	end
	
	begin
		face = entities.add_face points
		
		# store the indice array for this face
		face_indices[face] = indice_array
		
		if n != nil
			# flip the new face is it is not facing the correct direction according to the provided normals
			dot = face.normal.dot n
			if dot < 0.0
				face.reverse!
			end
		end
		
		if material != nil
			face.material = material
			if is_double_sided
				face.back_material = material
			end
			
			if(texcoord != nil)
				begin
					face.position_material face.material, pt_array, true
					if is_double_sided
						face.position_material face.back_material, pt_array, false
					end
				rescue
				end
			end
		end
	
		
	rescue #=> e
		#puts 'Error - face could not be created'
		# todo: count the number of faces that could not be created
	end

	i = i + 3
end

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.