moethu / SketchUpNET

SketchUp C# API - A C++/CLI API Wrapper for the Trimble(R) SketchUp(R) C API
MIT License
108 stars 34 forks source link

How to handle Surfaces part of a component but not an instance? #18

Open KevinHuyskens opened 6 years ago

KevinHuyskens commented 6 years ago

Each vertice that is part of a surface which is part of an instance you can use .GetTransformed on and you get the correct position of the vertice to build your mesh but some components aren't part of an instance and contain surfaces that aren't part of an instance so how do you go about positioning those vertices in the correct place?

Sorry I have to ask it here but I don't know where else to go, the documentation on SketchUp file structures is very limited.

KevinHuyskens commented 6 years ago

Perhaps an other way to put it, do you know of a way to get all the faces with the correct transform? Because at the moment some faces don't get transforms applied. Here is my class:

' class SketchUpReader { private Vector3 vertice = new Vector3(); private Vector3[] face = new Vector3[3]; UdpClient client = new UdpClient();

    List<string> faceStrings = new List<string>();

    public int verticeCount = 0;

    public void loadSkp(string path)
    {
        var currentTime = DateTime.Now;
        SketchUp skp = new SketchUp();
        if (skp.LoadModel(path, true))
        { 
            foreach(Group g in skp.Groups)
            {
                foreach(Instance i in g.Instances)
                {
                    Component comp = i.Parent as Component;

                    foreach(Surface s in g.Surfaces)
                    {
                        GetGroupInstanceSurfaceVertices(s, g, i);
                    }
                }
                foreach(Surface s in g.Surfaces)
                {
                    GetGroupSurfaceVertices(s, g);
                }
            }
            if (skp.Surfaces.Count == 0)
            {
                foreach (Instance i in skp.Instances)
                {
                    faceStrings.Add(new Vector3(1, 1, 1).ToTransformString());
                    faceStrings.Add(new Vector3(1, 1, 1).ToTransformString());
                    Component comp = i.Parent as Component;

                    foreach (Surface s in comp.Surfaces)
                    {
                        GetInstanceSurfaceVertices(s, i);
                    }

                    foreach (KeyValuePair<string, SketchUpNET.Component> c in skp.Components)
                    {
                        foreach (Instance instance in c.Value.Instances)
                        {
                            faceStrings.Add(new Vector3(1, 1, 1).ToTransformString());
                            faceStrings.Add(new Vector3(1, 1, 1).ToTransformString());

                            Component compo = instance.Parent as Component;

                            foreach (Surface s in compo.Surfaces)
                            {
                                GetNestedInstanceSurfaceVertices(s, i, instance);
                            }
                        }
                    }
                }
                new Thread(() =>
                {
                    Thread.CurrentThread.IsBackground = true;
                    client.SendData(faceStrings);
                }).Start();
            }
            else
            {
                foreach (Surface s in skp.Surfaces)
                {
                    GetSurfaceVertices(s, faceStrings);
                }
                new Thread(() =>
                {
                    Thread.CurrentThread.IsBackground = true;
                    client.SendData(faceStrings);
                }).Start();
            }

            File.WriteAllLines(@"c:\Users\Kevin\Desktop\testfile.txt", faceStrings);

            new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                Thread.Sleep(5000);
                client.SendData(new List<string> { "done" });
            }).Start();
        }
    }

    public void GetSurfaceVertices(Surface surface, List<string> stringList)
    {

        Mesh m = surface.FaceMesh;

        foreach(MeshFace mf in m.Faces)
        {
            verticeCount += 3;

            SetVertex(vertice, m.Vertices[mf.A]);
            face[0] = vertice;
            stringList.Add(vertice.ToString());

            SetVertex(vertice, m.Vertices[mf.B]);
            face[1] = vertice;
            stringList.Add(vertice.ToString());

            SetVertex(vertice, m.Vertices[mf.C]);
            face[2] = vertice;
            stringList.Add(vertice.ToString());
        }
    }

    public void GetInstanceSurfaceVertices(Surface surface, Instance i)
    {
        Mesh m = surface.FaceMesh;

        foreach (MeshFace mf in m.Faces)
        {
            verticeCount += 3;

            SetVertex(vertice, i.Transformation.GetTransformed(m.Vertices[mf.A]));
            face[0] = vertice;
            faceStrings.Add(vertice.ToString());

            SetVertex(vertice, i.Transformation.GetTransformed(m.Vertices[mf.B]));
            face[1] = vertice;
            faceStrings.Add(vertice.ToString());

            SetVertex(vertice, i.Transformation.GetTransformed(m.Vertices[mf.C]));
            face[2] = vertice;
            faceStrings.Add(vertice.ToString());
        }
    }

    public void GetGroupSurfaceVertices(Surface surface, Group g)
    {
        Mesh m = surface.FaceMesh;

        foreach (MeshFace mf in m.Faces)
        {
            verticeCount += 3;

            SetVertex(vertice, g.Transformation.GetTransformed(m.Vertices[mf.A]));
            face[0] = vertice;
            faceStrings.Add(vertice.ToString());

            SetVertex(vertice, g.Transformation.GetTransformed(m.Vertices[mf.B]));
            face[1] = vertice;
            faceStrings.Add(vertice.ToString());

            SetVertex(vertice, g.Transformation.GetTransformed(m.Vertices[mf.C]));
            face[2] = vertice;
            faceStrings.Add(vertice.ToString());
        }
    }

    public void GetGroupInstanceSurfaceVertices(Surface surface, Group g, Instance i)
    {
        Mesh m = surface.FaceMesh;

        foreach (MeshFace mf in m.Faces)
        {
            verticeCount += 3;

            SetVertex(vertice, g.Transformation.GetTransformed(i.Transformation.GetTransformed(m.Vertices[mf.A])));
            face[0] = vertice;
            faceStrings.Add(vertice.ToString());

            SetVertex(vertice, g.Transformation.GetTransformed(i.Transformation.GetTransformed(m.Vertices[mf.B])));
            face[1] = vertice;
            faceStrings.Add(vertice.ToString());

            SetVertex(vertice, g.Transformation.GetTransformed(i.Transformation.GetTransformed(m.Vertices[mf.C])));
            face[2] = vertice;
            faceStrings.Add(vertice.ToString());
        }
    }

    public void GetNestedInstanceSurfaceVertices(Surface surface, Instance rootInstance,Instance nestedInstance)
    {
        Mesh m = surface.FaceMesh;

        foreach (MeshFace mf in m.Faces)
        {
            verticeCount += 3;

            SetVertex(vertice, rootInstance.Transformation.GetTransformed(nestedInstance.Transformation.GetTransformed(m.Vertices[mf.A])));
            face[0] = vertice;
            faceStrings.Add(vertice.ToString());

            SetVertex(vertice, rootInstance.Transformation.GetTransformed(nestedInstance.Transformation.GetTransformed(m.Vertices[mf.B])));
            face[1] = vertice;
            faceStrings.Add(vertice.ToString());

            SetVertex(vertice, rootInstance.Transformation.GetTransformed(nestedInstance.Transformation.GetTransformed(m.Vertices[mf.C])));
            face[2] = vertice;
            faceStrings.Add(vertice.ToString());
        }
    }

    private void SetVertex(Vector3 vertex, Vertex skpVertex)
    {
        vertex.x = skpVertex.X;
        vertex.y = skpVertex.Y;
        vertex.z = skpVertex.Z;
    }

    public static bool ReformatModel(string filepath, string version, string newfilepath)
    {
        SketchUp skp = new SketchUp();
        SKPVersion v = SKPVersion.V2017;
        switch (version)
        {
            case "2014": v = SKPVersion.V2014; break;
            case "2015": v = SKPVersion.V2015; break;
            case "2016": v = SKPVersion.V2016; break;
            case "2017": v = SKPVersion.V2017; break;
            case "2018": v = SKPVersion.V2018; break;
        }
        return skp.SaveAs(filepath, v, newfilepath);
    }
}'
moethu commented 6 years ago

Hi @Kevinator123 so you want to get all surfaces as one list, correct? So my take would be:

  1. get all surfaces into a list
  2. walk through all instances and get the surfaces and add them to the list like this one: https://github.com/moethu/SketchUpNET/blob/master/SketchUp/SketchUpNET/SketchUpForDynamo/SketchUp.cs#L280-L308
KevinHuyskens commented 6 years ago

Thanks for answering, the way I do it right now is check each instance, surface and group on model level and keep on going down the nested components but I'm still missing faces somehow.

https://github.com/Kevinator123/SketchUpReader/blob/master/ReadSKPConsole/Program.cs

moethu commented 6 years ago

Did you check for nested instances etc?

KevinHuyskens commented 6 years ago

I think I checked all nested surfaces, foreach instance I get the parent component, for each of those components I draw the surfaces, I check the groups and check the instances. For each group I check the instances and their parent components and nested groups and for components I draw the surfaces, check for new instances and new groups. I also check for surfaces, groups and components on model level.

moethu commented 6 years ago

Are you able to check your SKP file to see which geometries haven't been imported? Where are they located? within a component or at root level simply in the model? What kind of geometry is it? Maybe it cannot be meshed?

KevinHuyskens commented 6 years ago

It definitely are just faces so I think it can be meshed, they are part of an instance. But what I just noticed is that everything that doesn't draw has as type: Type undefined. Perhaps that has something to do with it?

Then again some things that have type undefined do draw....

moethu commented 6 years ago

Type undefined sounds odd, can you share your skp model with me so I can have a look. And please point me to the failing faces.

KevinHuyskens commented 6 years ago

So here is a skp file that has a lot of missing faces: https://drive.google.com/open?id=1Qrv8ca_dGlpYQqXdsAImo9u-jls35JND

So that's how it's supposed to look and this is how it looks: image (Don't take into account the textures and colors, haven't spend time on that yet because it's not the main priority)

13704017891 commented 5 years ago

@ KevinHuyskens Hello, do you import SKP with unity?I am doing the same thing, can you give me some reference?

moethu commented 5 years ago

@KevinHuyskens , sorry just realizing you answered quite some time ago. I was wondering when I looked at your code: what about instances that contain other instances? and what about components containing components? both cases are not coughed.

KevinBME commented 5 years ago

@13704017891 Yes, I load the file externally and pass all the faces through with a named pipe. (haven't worked on this project for quiete some time). @moethu I'll try this when I have time, see if it works, I'll keep you posted once I get to it.

(Same person, different account)

KevinHuyskens commented 5 years ago

@moethu took a look at your suggestion just now, but your library's Instance object doesn't contain any Instances and Component doesn't contain any Components so I can't catch those cases :')

moethu commented 5 years ago

Did you check the Dynamo implementation as a reference? The components in there were able to catch all geometries so far. https://github.com/moethu/SketchUpNET/blob/master/SketchUp/SketchUpNET/SketchUpForDynamo/SketchUp.cs Maybe I was missing something, I will setup a Windows VM to test you implementation but please have a look if you got all the nested elements etc.

KevinHuyskens commented 5 years ago

So instead of going over my old code I started completely over, here is a code sample for writing out everything in a treeview in wpf (I excluded edges and curves because I don't need them).

Here is the sample: https://pastebin.com/XpRWYruK (start a new wpf project and add a treeview with name "treeView" if you want to use it yourself and change the model path and perhaps the namespace.)

Redoing it I can already see I missed some essential parts in my previous approach so I'll let you know how it goes from here on, but I've a feeling that I'm on the right track ;)

moethu commented 5 years ago

Let me know if anything is missing in the library