I have implemented an skp importer which works for 99% of skp objects even very complex one and fail with that “simple” one:
Basically, it is a very simple skp
-Model
– Group x Scale Transformation
— Image x Scale Transformation
– Face
With SDK (skp2xml sample) I’m unable to find in this model the link between the Group and the Image, it is like
-Model
– Group x Scale Transformation
– Image x Scale Transformation
– Face
So I can’t compose both transformation correctly and don’t know where I can look in.
A Sketchup importer is in “C”, I will answer from the perspective of the Ruby API.
Before I answer your question, I will comment on the model arrangement.
The tan colored square is a Group that contains an Image. Perhaps you wanted the group of the copper colored square. The copper colored scalloped roofing tile is loose geometry consisting of edges and a face. It has not been grouped. There is no associated transformation with its edges and face. Instead the edge start and end method return vertex objects that have the position of them in absolute coordinates.
The tan colored square is a Sketchup “Image” object nested inside of a group. That group’s transformation could be referenced with the Ruby API by:
That transformation is unscaled.
The tan colored image object is the only entity in the group, which is rare. The tan colored Image object’s transformation can be referenced with:
Many thanks for you answer.
Is there a way to output in Ruby like “image_t .print()” to display all values of an object
About my post :
1/ it was a visit card but I removed it before publishing the post for evident reason
2/ the file is a simplier version of this model that I want to import. This is simplier for me to debug.
I found that the reason for a bad import was when an image coming from a bitmap file is inside a group.
I am currently unable to find the link betewwen Group and image with C API based on skp2xml SDKsample.
So I have both (image and group) Trsf matrix with correct values, but I can’t assume I need to combine them because I do not find the way to find Image SOUNDCREAM_RAGNO is child of Group#1.
By doing this, whan importing, the image is not at the right position and right scale as it appears in this is the import result As you can see, 3 images on 5 are correct but the two in the middle are not. Seems also this Lisboa model does not have same design way on each square
And then you’ll need to multiply the image instance transform by the parent transform to get world coords (like in Ruby example)
The image polygon size you can get by SUImageGetDimensions
On your screenshots group is empty what (probably) means that you didn’t read Image-Typed instances from group entities.
SUTransformation trsf;
CTransform image_trsf;
SUImageGetTransform(image, &trsf); // <- this is local transform
image_trsf.SetMatrix(trsf.values);
by group (Group#1) transform?
You are passing XmlEntitiesInfo &entities_info which probably contains parent transform but you didn’t used it.
model_info_.entities_.component_instances_.push_back(imageInstance);
I’m not sure, but it looks like you are adding this image in to the model level not Group#1 level.
Image vertex (of course if the Image is child of the group) should be transformed by:
My problem is only that I am unable to find where is the link between group#1 and image so I can’t combine the two transformations that I already have. Group#1 seems empty although it holds image inside it.
SUEntitiesRef modelEntitiesRef = SU_INVALID;
SUModelGetEntities(modelRef, &modelEntitiesRef);
SUEntitiesGetNumGroups(modelEntitiesRef, &numGroups);
std::vector<SUGroupRef> groups(numGroups, SU_INVALID);
SUEntitiesGetGroups(modelEntitiesRef, numGroups, &groups[0], &numGroups);
for (auto &groupRef : groups)
{
SUEntitiesRef groupEntitiesRef = SU_INVALID;
SU_CALL(SUGroupGetEntities(groupRef, &groupEntitiesRef));
SUEntitiesGetNumImages(groupEntitiesRef, &numImages);
std::vector <SUImageRef> images(numImages, SU_INVALID);
SUEntitiesGetImages(groupEntitiesRef, numImages, &images[0], &numImages);
for (auto &imageRef : images)
// process images - now the parent transform is the groupTransform
}
Every group should have they entities, accessible by SUGroupGetEntities or this should be the same by SUGroupGetDefinition and then by SUComponentDefinitionGetEntities
A group is a special kind of component instance (that is hidden from the “In Model” component browser.)
So (being instance objects) groups do not own child entities, their definitions do.
Groups (like all component instances) have a component definition (whose “group?” flag is set true.)
In the Ruby API, there is a wrapper method: group.entities() that is a shortcut for group.definition.entities(). (The API was written to mimic the GUI interface, that obscures the fact that groups are really special component instances with definitions.)
In the C API, there is also the wrapper function that allows the direct access of a group definition’s entities collection, directly from the group instance. @RaPIT shows the use of SUGroupGetEntities() in the example above.
In both APIs, the return from these methods / functions is a reference to an Entities collection object, which is the same for the root level of the model object, and any component definition object (be it a component definition, a group definition or an Image definition.)
So FYI, in the SketchUp DOM, Images are special component instances also, that have a definition whose “image?” flag is set true. But be careful when accessing image objects. You should only do what is exposed to the APIs, as some image definition manipulation can corrupt the model file and crash the SketchUp application. (For this reason both APIs try to make it difficult to modify an Image object’s definition, which is meant to protect the SKP file data and prevent SketchUp crashes.)
However, accessing the image data via established API functions should not cause a problem.
Component definition should be threated as a “geometry template” or “class”, if you are going to export existing geometry you should write only GroupInstances / ComponentInstances.
In your example it looks a bit like you exported content of group definition at origin.
If I remove the line, it works for the visit card sample but all component based files are not any more imported. @DanRathbun said “So FYI, in the SketchUp DOM, Images are special component instances also, that have a definition whose “image?” flag is set true.” So image is written because of presence in Component Definition and also it presence in Group itself.
Geometry is written once only for definition and used by all instances like in SU.
For images I don’t know what to do to avoid it twice.
What I have done for my import is using skp_to_xml sample. Basicallly it fills C++ classes.
so the flow is : skp → xml classes → save in private format
In the SDK sample these classes are normally saved as xml. I am using them as helper.
The code is taken xmlexporter.cpp in C SDK skp_to_xml sample “SketchUpSDK\samples\C++\skp_to_xml\common”
I must admit I am a little bit lost on skp DOM. Question I’m usually wondering is when and where can I have the info (material, parent object, ) I need at some moment for complex models with groups and components or even both and in both direction Groups in Components, Components in Groups where material is on Component or Group and not on the end face itself. I am very close now to make it working well although.
Materials rule is (as far as I know, and of course if this is not the “Color by Layer” mode ) :
use face material if it was defined (SUFaceGetFrontMaterial / SUFaceGetBackMaterial)
if not, use first material that you found on the group/component level when you traversing up from a face to the model level, (SUDrawingElementGetMaterial)
if not, use the default one.
The simplest way, (I think it should work) try to treat Images as a “special type” of face, convert it to your-face-type.
Then this shouldn’t be necessary:
And this looks a bit like you’re adding any Images (wherever it is) to the root entities of the model.
I have tried your proposal :
`model_info_.definitions_.push_back(imageDefinition);
But in my case it can’t work.
So because of your help and your comments, here is how I have handled the problem :
void CXmlExporter::WriteComponentDefinition(SUComponentDefinitionRef component_definition) {
std::string name = GetComponentDefinitionName(component_definition);
....
// We need to avoid image export when going through definition
// it will be exported in component or group instances
options_.set_export_images(false);
WriteEntities(entities, info.entities_, CTransform());
options_.set_export_images(true);
....
}