This is the discussion forum for Helix Toolkit.
For bugs and new features, use the issue tracker located at GitHub.
Also try the chat room!
+2

Does Helix Toolkit work on UWP?

Garry Taylor 4 years ago 0

Hi everyone,

Just a quick question, does Helix Toolkit work on UWP? I've tried to build it, but lots of errors, so before I start looking into it further, is it even supposed to work?


Helix Toolkit has been amazing on WPF, just want to know if I can use on a UWP app?


Thanks


Garry

+2

Is there a way to create extruded 3d solid from planar polygon?

Anonymous 6 years ago 0
This discussion was imported from CodePlex

luanshixia wrote at 2013-03-02 03:35:

I am using HelixToolkit to create a simple city data visualization app. I need to extrude building plans from AutoCAD dwg file. ExtrudedVisual3D only result the side surface, without caps.

Rossie wrote at 2013-03-04 01:06:

Hi I had a similar requirement - but i had caps. The way I achieved it was to find the border edges of the polygon(s) and extrude them along the Z axis. But I implemented my own FindBorderEdges() method - because Helix3D's version did not entirely suit. Mainly because I wanted a contiguous list of edges - (Helix3D will put the output edges in the same sequence as the input edges - meaning that they may/may not be a contiguous list) I also wanted them in a particular winding order. I'll post my implementation - that might help you. (and perhaps the guys developing the Helix3D devs might want to use this code as well) I'll just paste in the main methods to do the work - i made a class called MeshGeometryHelper2. Let me know if i have missed anything - you might have to fiddle the source to fit your purpose.
        public static List<int> FindBorderEdges(MeshGeometry3D mesh)
        {
            var dict = new Dictionary<ulong, int>();

            for (int i = 0; i < mesh.TriangleIndices.Count / 3; i++)
            {
                int i0 = i * 3;
                for (int j = 0; j < 3; j++)
                {
                    int index0 = mesh.TriangleIndices[i0 + j];
                    int index1 = mesh.TriangleIndices[i0 + (j + 1) % 3];
                    int minIndex = Math.Min(index0, index1);
                    int maxIndex = Math.Max(index1, index0);
                    ulong key = CreateKey((UInt32)minIndex, (UInt32)maxIndex);
                    if (dict.ContainsKey(key))
                    {
                        dict[key] = dict[key] + 1;
                    }
                    else
                    {
                        dict.Add(key, 1);
                    }
                }
            }

            var edges = new List<int>();
            foreach (var kvp in dict)
            {
                // find edges only used by 1 triangle
                if (kvp.Value == 1)
                {
                    uint i0, i1;
                    ReverseKey(kvp.Key, out i0, out i1);
                    edges.Add((int)i0);
                    edges.Add((int)i1);
                }
            }

            var borderPoints = new List<Point>();
            mesh.Positions.ToList().ForEach(p => borderPoints.Add(new Point(p.X, p.Y)));

            var result = OrganizeEdges(edges, borderPoints);
            return result;
        }


        private static List<int> OrganizeEdges(List<int> edges, List<Point> positions)
        {
            var visited = new Dictionary<int, bool>();
            var edgeList = new List<int>();
            var resultList = new List<int>();
            var nextIndex = -1;
            while (resultList.Count < edges.Count)
            {
                if (nextIndex < 0)
                {
                    for (int i = 0; i < edges.Count; i += 2)
                    {
                        if (!visited.ContainsKey(i))
                        {
                            nextIndex = edges[i];
                            break;
                        }
                    }
                }

                for (int i = 0; i < edges.Count; i += 2)
                {
                    if (visited.ContainsKey(i))
                        continue;

                    int j = i + 1;
                    
                    int k = -1;
                    if (edges[i] == nextIndex)
                        k = j;
                    else if (edges[j] == nextIndex)
                        k = i;

                    if (k >= 0)
                    {
                        var edge = edges[k];
                        visited[i] = true;
                        edgeList.Add(nextIndex);
                        edgeList.Add(edge);
                        nextIndex = edge;
                        i = 0;
                    }
                }

                // calculate winding order - then add to final result.
                var borderPoints = new List<Point>();
                edgeList.ForEach(ei => borderPoints.Add(positions[ei]));
                var winding = CalculateWindingOrder(borderPoints);
                if (winding > 0)
                    edgeList.Reverse();

                resultList.AddRange(edgeList);
                edgeList = new List<int>();
                nextIndex = -1;
            }

            return resultList;
        }


        public static MeshGeometry3D Extrude(MeshGeometry3D surface, double z)
        {
            var borderIndexes = MeshGeometryHelper2.FindBorderEdges(surface);
            var borderPoints = new List<Point3D>();
            borderIndexes.ToList().ForEach(bi => borderPoints.Add(surface.Positions[bi]));

            var topPoints = borderPoints.ToList();
            var botPoints = borderPoints.Select(p => new Point3D(p.X, p.Y, p.Z + z)).ToList();
            
            var allPoints = new List<Point3D>();
            var allIndexes = new List<int>();
            var allNormals = new List<Vector3D>();

            // sides.
            allPoints.AddRange(topPoints);
            allPoints.AddRange(botPoints);

            for (int i = 0; i < topPoints.Count; i +=2)
            {
                int j = (i + 1) % topPoints.Count;

                allIndexes.Add(i);
                allIndexes.Add(j);
                allIndexes.Add(topPoints.Count + j);
                allIndexes.Add(topPoints.Count + j);
                allIndexes.Add(topPoints.Count + i);
                allIndexes.Add(i);

                var a = allPoints[i].ToVector3D();
                var b = allPoints[j].ToVector3D();
                var c = allPoints[topPoints.Count + j].ToVector3D();

                var n0 = b.Subtract(a).Cross(c.Subtract(a)).Unit();
                allNormals.Add(n0);
                allNormals.Add(n0);
                allNormals.Add(n0);
                allNormals.Add(n0);
            }

            var surfaceNormals = new List<Vector3D>();
            if (surface.Normals == null)
                surface.TriangleIndices.ToList().ForEach(i => surfaceNormals.Add(new Vector3D(0, 0, 1)));

            // top
            var count = allPoints.Count;
            var topSurfacePoints = surface.Positions.Select(p => new Point3D(p.X, p.Y, p.Z + z)).ToList();
            var topNormals = surfaceNormals.ToList();
            allPoints.AddRange(topSurfacePoints);
            allNormals.AddRange(topNormals);
            var topSurfaceIndexes = surface.TriangleIndices.Select(i => count + i).ToList();
            AddTriangleIndexes(topSurfaceIndexes, allIndexes, false);

            // bottom
            count = allPoints.Count;
            var botSurfacePoints = surface.Positions.ToList();
            var botNormals = surfaceNormals.Select(n => n.Flip()).ToList();
            allPoints.AddRange(botSurfacePoints);
            allNormals.AddRange(botNormals);
            var botSurfaceIndexes = surface.TriangleIndices.Select(i => count + i).ToList();
            AddTriangleIndexes(botSurfaceIndexes, allIndexes, true);

            var mesh = new Mesh3D(allPoints, allIndexes);
            var meshGeom = mesh.ToMeshGeometry3D();
            meshGeom.Normals = new Vector3DCollection(allNormals);

            if (z < 0) 
                ReverseWinding(meshGeom);

            var simple = Simplify(meshGeom);
            return simple;
        }

        private static void AddTriangleIndexes(List<int> triangleIndices, List<int> allIndexes, bool reverseWindingOrder)
        {
            for (int i = 0; i < triangleIndices.Count; i += 3)
            {
                var i0 = triangleIndices[i + 0];
                var i1 = triangleIndices[i + 1];
                var i2 = triangleIndices[i + 2];
                if (reverseWindingOrder)
                    allIndexes.AddRange(new[] { i2, i1, i0 });
                else
                    allIndexes.AddRange(new[] { i0, i1, i2 });
            }
        }

        public static void ReverseWinding(MeshGeometry3D mesh)
        {
            var indices = mesh.TriangleIndices.ToList();
            var flippedIndices = new List<int>();
            AddTriangleIndexes(indices, flippedIndices, true);
            mesh.TriangleIndices = new System.Windows.Media.Int32Collection(flippedIndices);
        }

       /// <summary>
        /// returns 1 for CW, -1 for CCW, 0 for unknown.
        /// </summary>
        public static int CalculateWindingOrder(IList<Point> points)
        {
            // the sign of the 'area' of the polygon is all we are interested in.
            var area = CalculateSignedArea(points);
            if (area < 0.0)
                return 1;
            else if (area > 0.0)
                return -1;        
            return 0; // error condition - not even verts to calculate, non-simple poly, etc.
        }

        public static double CalculateSignedArea(IList<Point> points)
        {
            double area = 0.0;
            for (int i = 0; i < points.Count; i++)
            {
                int j = (i + 1) % points.Count;
                area += points[i].X * points[j].Y;
                area -= points[i].Y * points[j].X;
            }
            area /= 2.0;

            return area;
        }

+1

Tubidy Mobile Music Video Mp3

sdt 3 years ago updated by anonymous 2 years ago 1

Years ago, we had no complaints to spend a hundred dollars to buy tape and CD. Then, online downloading music has not been popularized; no one has tasted the initial benefits of music downloading for free. When Internet starts to prevail among the masses, a sea of free music websites have sprung up. Thus, consumers are accustomed to enjoy free services. When used to have free lunch, who are willing to pay out-of-pocket for music?
As a result, even though the public voice is appealing to everyone endlessly, "pay for online downloading music" will still become a norm. While, for the public, both the shift of consumption habits and the adaptation of charge services require us to take a little patience to await. During the process, it is likely for traditional music sales model to search for a suitable new development model.


Mp3 Download Site: Tubidy Tubidy Tubidy Tubidy

+1

HelixToolkit.Wpf.SharpDX - Custom Shader

Anonymous 6 years ago 0
This discussion was imported from CodePlex

eonxxx wrote at 2014-08-14 12:11:

hi there a chance to use custom shaders in HelixToolkit.Wpf.SharpDX?
how does it works, if so?

do i need to use fx0.5 effects for it?

is it possible to use generated (shaderbytecode.compilefromfile) bytecode?
+1

Texture coordinates from ObjReader

Anonymous 6 years ago 0
This discussion was imported from CodePlex

Lolligeir wrote at 2013-03-22 18:08:

Hey! Thanks for an awesome tool.

I am reading some obj files for a ray tracer and I have managed to read the Points of each triangle and the normals but the texture coordinate don´t seem to be working correctly. This is how I am reading the file:
            ObjReader r = new ObjReader();
            Model3DGroup model = r.Read(modelUrl);
            GeometryModel3D gm1 = (GeometryModel3D)model.Children[0];
            MeshGeometry3D mg1 = (MeshGeometry3D)gm1.Geometry;
            Vector3DCollection normals = mg1.Normals;     
            System.Windows.Media.PointCollection textureCoordinates = mg1.TextureCoordinates;
            System.Windows.Media.Int32Collection indices = mg1.TriangleIndices;
            Point3DCollection points = mg1.Positions;
            
            

            for (int index = 0; index < indices.Count; index += 3)
            {
                Point3D p0 = points[indices[index]];
                Point3D p1 = points[indices[index + 1]];
                Point3D p2 = points[indices[index + 2]];          
                
                Vector3D n0 = normals[indices[index]];
                Vector3D n1 = normals[indices[index + 1]];
                Vector3D n2 = normals[indices[index + 2]];

                System.Windows.Point t0 = textureCoordinates[indices[index]];
                System.Windows.Point t1 = textureCoordinates[indices[index + 1]];
                System.Windows.Point t2 = textureCoordinates[indices[index + 2]];
}
      
This loads the correct points and normals but the texture coordinates come out wrong. Am I approacing this incorrectly? How do you read the correct texture coordinate for every face?

The obj file I have been using (Removed text after vertices to get the objReader to read it) : http://cs.wellesley.edu/~cs307/tw/objects/cube-textures.obj

Best regards,
Viktor
+1

How to access different component from .3ds file

Anonymous 6 years ago 0
This discussion was imported from CodePlex

GhufranZahidi wrote at 2012-11-20 10:04:

Hi 

I want to access multiple component from .3ds file by name and try to move particular component, is it possible if yes then give method name, please reply

+1

Storyboard animation

Anonymous 6 years ago 0
This discussion was imported from CodePlex

xyxa wrote at 2012-07-14 15:56:

Thanks so much for very useful toolkit.

But unfortunately I could not create a storyboard animation via Blend for any MeshElement3D. It's strange, because I can create such animation for ModelVisual3D. What is the reason for this behavior and Is there any ways to solve it?

+1

MeshGeometryHelper Cut Method

Anonymous 6 years ago 0
This discussion was imported from CodePlex

badgerbadger wrote at 2012-07-26 16:50:

I would like to modify the MeshGeometryHelper.Cut method so that it (also) meshes the opening created by the planar cut (i.e. currently the mesh is open at the location of the plane, I need a closed surface)

Can anyone figure out a neat way of achieving this in the Cut method? (Objo? :) )  (maybe uncommenting some of the commented-code in the Cut method achieves this..?)

Otherwise I guess I will have to get a contour of the planar mesh, attempt to mesh that surface and add to the Cut mesh - but a bit messy.


objo wrote at 2012-08-09 00:59:

Yes, you could change the cut method to also provide the contour(s). See the GetContourSegments...

When you have the contour(s), you can use the MeshBuilder.AddPolygonByCuttingEars to triangulate by the cutting/ears method (easy algorithm, but not very efficient).


badgerbadger wrote at 2012-08-09 10:41:

Many thanks Objo, yes I ended up doing something similar but used the AddPolygon instead of CuttingEars version (which I'll now investigate). I meant to post my hack but moved on to the next problem. Here is the mk1 code ( meshOrig is the original mesh while cutMesh is after the plane cut has been applied; plane is the cut plane).

I should add my code was not required to produce a nice mesh, it is only an intermediate step towards a bigger problem involving segmenting a mesh, so if others use it, it is worth investigating replacing AddPolygon (which applies a fan mesh)..

        private static MeshGeometry3D MeshPlaneCut(MeshGeometry3D meshCut, MeshGeometry3D meshOrig, Plane3D plane)
        {
            //Store the positions on the cut plane
            var segments = MeshGeometryHelper.GetContourSegments(meshOrig, plane.Position, plane.Normal).ToList();

            //assumes largest contour is the outer contour!
            IList<Point3D> vertexPoints = MeshGeometryHelper.CombineSegments(segments, 1e-6).ToList().OrderByDescending(x=>x.Count).First();

            //meshCut the polygon opening and add to existing cut mesh
            var builder = new MeshBuilder(false,false);
            builder.Append(meshCut.Positions, meshCut.TriangleIndices);
            builder.AddPolygon(vertexPoints);
           
            MeshGeometry3D mg3D = builder.ToMesh();

            return mg3D;
        }


ulissespi wrote at 2012-12-24 08:06:

I'm also interested in having a MeshGeometryHelper.Cut that as result creates a solid (non hollow) mesh.

I changed the ApplyCuttingPlanesToModel method in the CuttingPlaneGroup.cs file, replacing the call   

g = MeshGeometryHelper.Cut(g, p, n);

by    

g = MeshGeometryHelper.MeshPlaneCut(g, p, n);   

to use the method described in the previous post, but obviously it didn't work as the parameters are not the same.

Could you please give a bit more detail on how do you call your new method?

(maybe have a piece of the calling code) 

 

Or if someone else found another way of resolving this issue, other code examplesare wellcome.


badgerbadger wrote at 2012-12-24 11:39:

Hi Ulissepi - I should point out that my problem wasn't concerned with drawing a cut (and closed) mesh, only in calculating the mesh so that I could apply a contour algorithm to it. If you need to display the visual then something more sophisticated will be required.

I've tried to pick out the relevant bits from my code. It's been a while so hopefully I have included everything relevant. Hope it helps!

Geometry3D originalGeometry = model.Geometry;
//create a copy of the mesh
var g = originalGeometry as MeshGeometry3D;
MeshGeometry3D gOrig = g.Clone();

//Cut the Mesh and then apply the cutplane

//cp, p & n are the cut plane (Plane3D) and the position (Point3D) and the normal (Vector3D) of the plane

g = MeshGeometryHelper.Cut(g, p, n);

g = MeshPlaneCut(g, gOrig, cp);

GeometryModel3D gm3d = model.Clone();
 gm3d.Geometry = g;

+1

Collision Detection

Anonymous 6 years ago updated by anonymous 3 years ago 3
This discussion was imported from CodePlex

BCBlanka wrote at 2012-11-10 08:47:

Hello,

 

Is there a way to detect collision between 3D models?

 

Thanks

Blanka


objo wrote at 2012-11-11 22:14:

sorry, no collision detection is implemented in this library. But it would be interesting to see integration of the models defined here with bullet or some other physics library! 

http://bulletphysics.org/
http://code.google.com/p/bulletsharp/
http://www.ode.org/
http://newtondynamics.com 


bcblanka wrote at 2012-11-12 06:40:

Thanks for the prompt response.

 

Blanka


davidop wrote at 2013-05-28 16:53:

Did you find the solution? What library do you recommend? Do you have any example?

BCBlanka wrote at 2013-05-29 10:10:

I ended up comparing the bounds of the models (Rect3D) and checking their intersection. This was enough for what I needed.

davidop wrote at 2013-05-30 11:00:

Do not you will have a small example? I need it for when moving objects (ModelVisual3D) with the mouse

objo wrote at 2013-06-07 12:01:

A small collision detection demo is on the wish list! Simple geometries (boxes) would be sufficient. Also a larger demo combining WPF3D and one of the well-known physics engines would be very interesting to see. Sorry, I don't have time to do this myself at the moment :)