GithubHelp home page GithubHelp logo

helix-toolkit / helix-toolkit Goto Github PK

View Code? Open in Web Editor NEW
1.8K 114.0 653.0 349.53 MB

Helix Toolkit is a collection of 3D components for .NET.

Home Page: http://helix-toolkit.org/

License: MIT License

C# 96.95% Batchfile 0.01% HLSL 3.03%
sharpdx c-sharp wpf helix-toolkit uwp 3d 3d-engine data-visualization dotnet directx

helix-toolkit's Introduction

HelixToolkit

Helix Toolkit

Helix Toolkit is a collection of 3D components for .NET Framework.

HelixToolkit.WPF: Adds variety of functionalities/models on the top of internal WPF 3D models (Media3D namespace).

HelixToolkit.Core.WPF: Adds variety of functionalities/models on the top of internal .NET Core WPF 3D models (Media3D namespace).

HelixToolkit.SharpDX.WPF: Custom 3D Engine and XAML/MVVM compatible Scene Graphs based on SharpDX(DirectX 11) for high performance usage.

HelixToolkit.UWP: Custom 3D Engine and XAML/MVVM compatible Scene Graphs based on SharpDX(DirectX 11) for Universal Windows App.

HelixToolkit.SharpDX.Core: Custom 3D Engine and Scene Graphs based on SharpDX(DirectX 11) for netstandard and .NET Core.

HelixToolkit.SharpDX.Core.Wpf: Wpf Wrapper Components based on HelixToolkit.SharpDX.Core for .NET Core Wpf.

HelixToolkit.WinUI: Custom 3D Engine and XAML/MVVM compatible Scene Graphs based on SharpDX(DirectX 11) for WinUI.

HelixToolkit.SharpDX.Assimp: Assimp.Net 3D model importer/expoter support for HelixToolkit.SharpDX Components.

Examples: Please download full source code to run examples. Or download compiled version

License: MIT Build status Release Chat

Description Value
Web page http://helix-toolkit.github.io/
Wiki https://github.com/helix-toolkit/helix-toolkit/wiki
Documentation http://helix-toolkit.readthedocs.io/
Chat https://gitter.im/helix-toolkit/helix-toolkit
Source repository http://github.com/helix-toolkit/helix-toolkit
Latest build http://ci.appveyor.com/project/holance/helix-toolkit
Issue tracker http://github.com/helix-toolkit/helix-toolkit/issues
NuGet packages http://www.nuget.org/packages?q=HelixToolkit
Nightly build https://www.myget.org/F/helixtoolkit-nightly
StackOverflow http://stackoverflow.com/questions/tagged/helix-3d-toolkit
Twitter https://twitter.com/hashtag/Helix3DToolkit

Project Build

Visual Studio 2019. Windows 10 SDK (Min Ver.10.0.18362.0).

Notes

1. Right-handed Cartesian coordinate system and row major matrix by default

HelixToolkit default is using right-handed Cartesian coordinate system, including Meshbuilder etc. To use left-handed Cartesian coordinate system (Camera.CreateLeftHandedSystem = true), user must manually correct the triangle winding order or IsFrontCounterClockwise in raster state description if using SharpDX. Matrices are row major by default.

2. Performance Topics for WPF.SharpDX and UWP.

3. Following features are not supported currently on FeatureLevel 10 graphics card:

FXAA, Order Independant Transparent Rendering, Particle system, Tessellation.

4. Wiki and useful External Resources on Computer Graphics.

HelixToolkit Library Structure

WPF Internal 3D Engine (DirectX9)

graph TD
    wpf[WPF Framework] --> hxWpf[HelixToolkit.Wpf]
    wpf --> hxCoreWpf[HelixToolkit.Core.Wpf]

HelixToolkit DirectX11 Engine

graph TD
    hx[HelixToolkit] --> dx11[DirectX11 Engine]    
    dx11 --> hxSharpDX[HelixToolkit.Wpf.SharpDX]
    dx11 --> hxUWP[HelixToolkit.UWP]
    dx11 --> hxCore[HelixToolkit.SharpDX.Core]
    hxCore --> hxWinUI[HelixToolkit.SharpDX.Core.Wpf]
    hxCore --> hxSharpDXCoreWpf[HelixToolkit.WinUI]
    hxSharpDX --> hxAssimp[HelixToolkit.SharpDX.Assimp]
    hxUWP --> hxAssimp
    hxCore --> hxAssimp

Bug Report

Please use the following template to report bugs.

  • Version: [Example: 2.20]
  • Package: [Example: Helixtoolkit.Wpf]
  • Issue:
  • Reproduce Steps:
  • Sample Code:

News

2024-02-27

v2.25.0 releases are available on nuget. Release Note

Changes (Please refer to Release Note for details)

2023-03-17

Nightly build myget feed link has been updated to: https://www.myget.org/F/helixtoolkit-nightly

helix-toolkit's People

Contributors

ando23 avatar b3zaleel avatar benglin avatar beppemarazzi avatar cbenghi avatar cchanibal avatar chaossorcerer avatar chrkon avatar cobracalle avatar dermeister0 avatar dgwaldo avatar edwardzhu avatar eriove avatar federgraph avatar garyjohnson avatar holance avatar iluvatar82 avatar jeremyansel avatar johnsonlu avatar jotschgl avatar maunguyenvan avatar mdelanno avatar miquik avatar nedmech avatar nordaj avatar objorke avatar sineumann avatar smischke avatar twsl avatar zhzg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

helix-toolkit's Issues

ModelViewer error when export to XAML

This issue was imported from CodePlex

Aeon wrote 2012-08-06 at 23:19
The ModelViewer (HelixToolkit-2012.3.77.1\Examples\ModelViewer) does not correctly export to XAML when this export option is selected, instead it exports to XML.

Problem after changing ViewCube Text

This issue was imported from CodePlex

PeterGAT wrote 2013-07-05 at 05:17
I wanted to be able to change the text on the view cube (as shown below). When I did this the hot spot for the viewcube getting focus didn't seem to coincide with the view cube anymore and clicking on the view cube did not rotate the view direction. When
I remove the xaml for the viewcube text it works fine. My helixviewport3D is inside a datatemplate for a avalondock document. I am also hittesting the excavation visual.

 
                                 
                                    
                                        
                                    
                                
                                    
                                    

                                    
                                        
                                            
                                        
                                    
                                        
                                

PS. I really like the toolkit :-)

BillboardTextVisual3D Material ignored

This issue was imported from CodePlex

survivorx wrote 2013-09-25 at 10:29
Hi,

I'm using the Helix 3D Toolkit to visualize machine automation. It saves me a lot of work. But I've stumbled across some issues:

BillboardTextVisual3D ignores the Material property and always sets it to:

this.Material = new DiffuseMaterial(new ImageBrush(rtb));

Often, there is a need to show labels independent of lighting. My quick hack is:

this.Material = new EmissiveMaterial(new ImageBrush(rtb));

But there should be a smarter solution that uses the Material property (set from outside).

Since I'm using Helix in source code, I can workaround such issues, but I'd prefer to stay close to the original to profit from it's development.

Regards

Stefan

objo wrote 2013-09-25 at 11:05
thanks for the feedback!

Can we replace with

            var brush = new ImageBrush(rtb);

            if (this.Material == null)
            {
                this.Material = new DiffuseMaterial(brush);
            }
            else
            {
                // Change brush of current material
                var em = this.Material as EmissiveMaterial;
                if (em != null)
                {
                    em.Brush = brush;
                }

                var dm = this.Material as DiffuseMaterial;
                if (dm != null)
                {
                    dm.Brush = brush;
                }
            }

survivorx wrote 2013-09-25 at 12:02
The problem is you set this.Material = null if (string.IsNullOrEmpty(this.Text)) and the text of my labels is null at the beginning unless the connection to the machine is established. So one ether has to save the material before setting it null (for hiding
the visual) and restoring it afterwards or the solution you proposed "MaterialType { Diffuse, Emissive } property".

Generally, I'm thinking about implementing an attached property like Object3D.Hidden="True" which allows to hide Visual3D and Model3D objects by setting the material to null but saving the material in a dictionary and restoring it if Object3D.Hidden="False".
This attached property needs to listen to Loaded / Unloaded and MaterialChanged to update the dictionary... just an idea because there doesn't seem to be a way to switch a scene graph object invisible (other than removing it.

objo wrote 2013-09-26 at 22:46
Does the latest change help? I could not get the EmissiveMaterial to work properly, what is missing?

The attached property is a good idea, I would be glad to include it here. It should be possible to store the material in another attached property to avoid the dictionary! It should also work on groups of Visual3D and Model3Ds...

objo wrote 2013-09-29 at 09:31
I added this as
https://helixtoolkit.codeplex.com/workitem/10003

survivorx wrote 2013-09-29 at 23:24
Your changes using MaterialType="Emissive" are working for me. Thanks a lot!

Trouble Serializing: "Cannot serialize member HelixToolkit.Wpf.ExtrudedVisual3D.TextureCoordinates ... because it is an interface."

I am attempting to serialize an object for MSMQ.

[2014-09-03 21:45:35,525] caught Exception: ToString(): System.InvalidOperationException: There was an error reflecting type 'foo.bar.graphics.ConnectionVisual3D'. ---> System.InvalidOperationException: There was an error reflecting property 'Tube'. ---> System.InvalidOperationException: There was an error reflecting type 'HelixToolkit.Wpf.TubeVisual3D'. ---> System.InvalidOperationException: Cannot serialize member 'HelixToolkit.Wpf.ExtrudedVisual3D.TextureCoordinates' of type 'System.Collections.Generic.IList1[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]', see inner exception for more details. ---> System.NotSupportedException: Cannot serialize member HelixToolkit.Wpf.ExtrudedVisual3D.TextureCoordinates of type System.Collections.Generic.IList1[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] because it is an interface.
[...]

I'm using XMLFormatter, like I usually do, but this is the first time I have had trouble with objects within objects, and the errors are pointing toward the helix source, as in:

System.NotSupportedException: Cannot serialize member HelixToolkit.Wpf.ExtrudedVisual3D.TextureCoordinates of type System.Collections.Generic.IList`1[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] because it is an interface.

I read that yuo can sometimes supply the formatter with the classes to use (see immediately below), but this complaint is because it apparently is being told to serialize an Interface...


[C# example from http://stackoverflow.com/questions/25559897/serialize-deserialize-a-dynamic-object]

static bool Save(Animal animal)
{
var lListOfAnimals = (from lAssembly in AppDomain.CurrentDomain.GetAssemblies()
from lType in lAssembly.GetTypes()
where typeof(Animal).IsAssignableFrom(lType)
select lType).ToArray();

    System.Xml.Serialization.XmlSerializer ListSer = new System.Xml.Serialization.XmlSerializer(typeof(Animal), lListOfAnimals);

[code:]

Me.TheQ = New MessageQueue(qPath)
'
' Create a new message.
'
Me.MsgTo = New Message(connectionEntry, New XmlMessageFormatter(New Type() {GetType(bar.graphics.ConnectionVisual3D)}))
With Me.MsgTo
.AcknowledgeType = AcknowledgeTypes.PositiveReceive Or AcknowledgeTypes.PositiveArrival
.Priority = MessagePriority.Normal
End With
'
' set what will be sent with message... overrides queue defaults (if different)...
'
TheQ.MessageReadPropertyFilter.ArrivedTime = True
TheQ.MessageReadPropertyFilter.SentTime = True
TheQ.MessageReadPropertyFilter.CorrelationId = True
TheQ.MessageReadPropertyFilter.Id = True
TheQ.Formatter = New XmlMessageFormatter(New Type() {GetType(bar.graphics.ConnectionVisual3D)})
'
' Send the event to the queue.
'
TheQ.Send(MsgTo)


Public Class ConnectionVisual3D
    Inherits ModelVisual3D
    Implements INotifyPropertyChanged

[...]
Public Property Tube As TubeVisual3D
Get
Return _tube
End Get
Set(value As TubeVisual3D)
'If Not value.Equals(_tube) Then
_tube = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Tube"))
'End If
End Set
End Property

...so inside ConnectionVisual3D there are objects like the TubeVisual3D.

Full trace:

[2014-09-03 21:45:30,883] caught Exception: ToString(): System.InvalidOperationException: There was an error reflecting type 'foo.bar.graphics.ConnectionVisual3D'. ---> System.InvalidOperationException: There was an error reflecting property 'Tube'. ---> System.InvalidOperationException: There was an error reflecting type 'HelixToolkit.Wpf.TubeVisual3D'. ---> System.InvalidOperationException: Cannot serialize member 'HelixToolkit.Wpf.ExtrudedVisual3D.TextureCoordinates' of type 'System.Collections.Generic.IList1[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]', see inner exception for more details. ---> System.NotSupportedException: Cannot serialize member HelixToolkit.Wpf.ExtrudedVisual3D.TextureCoordinates of type System.Collections.Generic.IList1[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] because it is an interface.
--- End of inner exception stack trace ---
at System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc, MemberInfo member, Type type)
at System.Xml.Serialization.StructModel.GetPropertyModel(PropertyInfo propertyInfo)
at System.Xml.Serialization.StructModel.GetFieldModel(MemberInfo memberInfo)
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Messaging.XmlMessageFormatter.Write(Message message, Object obj)
at System.Messaging.Message.AdjustToSend()
at System.Messaging.MessageQueue.SendInternal(Object obj, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
at System.Messaging.MessageQueue.Send(Object obj)
at foo.bar.messaging.ConnV3DQueue.SendMessage(ConnectionVisual3D connectionEntry, String qPath) in D:\Repositories\fooRedmine\v1\foo_v1\bar\messaging\ConnV3DQueue.vb:line 174, Last Milliseconds: 13.0008 [FATAL] Machine: DOOZY User: Pat Process: 53 CallingMethod: foo.bar.messaging.ConnV3DQueue.SendMessage LineNumber: 194

Is this something that source can resolve, or do I need to go about serialization completely differently?

MeshBuilder: AddPyramid, AddOctahedron and AddTetrahedron

This issue was imported from CodePlex

stfx wrote 2013-11-14 at 19:47
I changed your pyramid mesh generation code to allow creating pyramids facing into the specified direction much like the cube faces. Additionally this then allows generating octahedron meshes easily.

        public void AddPyramid(Point3D center, Vector3D normal, Vector3D up, double sideLength, double height)
        {
            var right = Vector3D.CrossProduct(normal, up);
            var n = normal * sideLength / 2;
            up *= height / 2;
            right *= sideLength / 2;

            var p1 = center - n - up - right;
            var p2 = center - n - up + right;
            var p3 = center + n - up + right;
            var p4 = center + n - up - right;
            var p5 = center + up;

            this.AddTriangle(p1, p2, p5);
            this.AddTriangle(p2, p3, p5);
            this.AddTriangle(p3, p4, p5);
            this.AddTriangle(p4, p1, p5);
        }

        public void AddOctahedron(Point3D center, Vector3D normal, Vector3D up, double sideLength, double height)
        {
            AddPyramid(center + up / 4, normal, up, sideLength, height / 2);
            AddPyramid(center - up / 4, -normal, -up, sideLength, height / 2);
        }

objo wrote 2013-11-19 at 13:38
AddPyramid: ok

AddOctahedron: not ok - duplicated triangles inside the octahedron

Should have similar overload for AddBox

** Closed by objo 11/19/2013 5:38AM

stfx wrote 2013-11-20 at 00:16
about octahedron, are you sure? the pyramid does not have a bottom face so having two pyramids mirrored on an axis should produce exactly 8 triangles.

btw since you want to still have the other pyramid overload function you should change the z-offset to be consistent with the added overload. I made the z-position in the new function exactly in the middle of the pyramid (+/- height / 2) but the old function
expects the z-position to be at the very bottom of the pyramid.

objo wrote 2013-11-20 at 08:00
you are right! I was too quick :) But I think this should be changed - the AddPyramid should add a closed mesh (to close the base could be a parameter).

I agree that center should be in the center (I prefer volumetric, not h/2) or renamed to position (at the base).

I think the parameters "up" and "normal" are confusing, can you suggest better names?

I agree, AddOctahedron and possibly AddTetrahedron can be added.

Examples or unit tests must also be created.

Snapping Manipulators

This issue was imported from CodePlex

objo wrote 2013-09-25 at 09:11
[discussion:456890]

Implement snapping for the manipulators.

Properties that can be snapped

  • the Value property
  • the Position (Translation: snapped along the Direction vector, Rotation: snapped by angle)

Aybe wrote 2013-11-13 at 18:10
Hello objo !

Do you have an approximate idea when the feature will be implemented ?

Best regards

objo wrote 2013-11-19 at 22:19
Hello Aybe,

sorry, I don't know anyone working on this issue!

But this is open source, feel free to fork and give it a go! Remember to add examples.

I also recommend adding some comments here on how it will be implemented since the description is not very clear...

Make ModelImporter thread safe

This issue was imported from CodePlex

pfresnay wrote 2013-09-20 at 18:59
Some models are heavy to load, ModelImporter should be thread safe to allow background loading without freezing UI.

Trying to load a model in a background thread throw an InvalidOperationException due to not freezed WPF 3D objects.

objo wrote 2013-09-25 at 09:06
Did you try freezing the model (including all geometries etc) after loading and before adding it to the view?

Should the elements always be created on the UI thread?

Can you make a small background loading example that fails.

pfresnay wrote 2013-09-25 at 10:20
@objo thanks for feedback.

See attached VS2012 project for example.

I looked at ModelImporter code, it seems that some elements are created using default elements that were previously created in UI thread without being freezed.

ViewCube decoration

This issue was imported from CodePlex

eugenco wrote 2012-06-10 at 15:53
Here some features:

Font properties (size,color,ect.) for ViewCube sides.

Ability place different image on each side of Viewcube.

(in some langs "Top" word and others is more longer than in English)

FindNearest not supporting MatrixCamera

This issue was imported from CodePlex

zbw911 wrote 2013-08-23 at 12:12
My Code :

   public static bool FindNearest(
        Viewport3D viewport, Point position, out Point3D point, out Vector3D normal, out DependencyObject visual)
    {
        var camera = viewport.Camera as ProjectionCamera;
        var matrixCamera = viewport.Camera as MatrixCamera;


        if (camera == null && matrixCamera == null)
        {
            point = new Point3D();
            normal = new Vector3D();
            visual = null;
            return false;
        }


        Point3D cameraPosition;

        if (camera != null)
        {
            cameraPosition = camera.Position;
        }
        else
        {
            var matrix = matrixCamera.ProjectionMatrix;
            //http://math.stackexchange.com/questions/82602/how-to-find-camera-position-and-rotation-from-a-4x4-matrix
            cameraPosition = new Point3D(matrix.M13, matrix.M23, matrix.M33);// matrixCamera.ProjectionMatrix;
        }



        var hitParams = new PointHitTestParameters(position);

        double minimumDistance = double.MaxValue;
        var nearestPoint = new Point3D();
        var nearestNormal = new Vector3D();
        DependencyObject nearestObject = null;

        VisualTreeHelper.HitTest(
            viewport,
            null,
            delegate(HitTestResult hit)
            {
                var rayHit = hit as RayMeshGeometry3DHitTestResult;
                if (rayHit != null)
                {
                    var mesh = rayHit.MeshHit;
                    if (mesh != null)
                    {
                        var p1 = mesh.Positions[rayHit.VertexIndex1];
                        var p2 = mesh.Positions[rayHit.VertexIndex2];
                        var p3 = mesh.Positions[rayHit.VertexIndex3];
                        double x = p1.X * rayHit.VertexWeight1 + p2.X * rayHit.VertexWeight2
                                   + p3.X * rayHit.VertexWeight3;
                        double y = p1.Y * rayHit.VertexWeight1 + p2.Y * rayHit.VertexWeight2
                                   + p3.Y * rayHit.VertexWeight3;
                        double z = p1.Z * rayHit.VertexWeight1 + p2.Z * rayHit.VertexWeight2
                                   + p3.Z * rayHit.VertexWeight3;

                        // point in local coordinates
                        var p = new Point3D(x, y, z);

                        // transform to global coordinates

                        // first transform the Model3D hierarchy
                        var t2 = GetTransform(rayHit.VisualHit, rayHit.ModelHit);
                        if (t2 != null)
                        {
                            p = t2.Transform(p);
                        }

                        // then transform the Visual3D hierarchy up to the Viewport3D ancestor
                        var t = GetTransform(viewport, rayHit.VisualHit);
                        if (t != null)
                        {
                            p = t.Transform(p);
                        }

                        double distance = (cameraPosition - p).LengthSquared;
                        if (distance < minimumDistance)
                        {
                            minimumDistance = distance;
                            nearestPoint = p;
                            nearestNormal = Vector3D.CrossProduct(p2 - p1, p3 - p1);
                            nearestObject = hit.VisualHit;
                        }
                    }
                }

                return HitTestResultBehavior.Continue;
            },
            hitParams);

        point = nearestPoint;
        visual = nearestObject;
        normal = nearestNormal;

        if (minimumDistance >= double.MaxValue)
        {
            return false;
        }

        normal.Normalize();
        return true;
    }

Fly-mode

This issue was imported from CodePlex

stfx wrote 2013-11-20 at 01:11
Now I recently added this movement mode using arrow/WASD keys as some users seem to find this more intuitive/easier to use. The longer the user presses the button the faster he moves. Holding SHIFT increases movement further. Maybe you find it interesting
as it is kinda similar to how games usually let you fly around (unreal tournament, counter strike).

1: Add an enum

    [Flags]
    public enum CameraDirection
    {
        None = 0,
        Forward = 0x1,
        Backward = 0x2,
        Left = 0x4,
        Right = 0x8,
        Up = 0x10,
        Down = 0x20,
    }

2: Add global variables in the camera controller

        private CameraDirection flyDirection;
        private bool isFlyRotating;
        private double flyIncrement;

3: Add code for different rotation around fixed point - using isFlyRotating

        public void Rotate(double dx, double dy)
        {
            ProjectionCamera c = Camera;

            var up = new Vector3D(0, 0, 1);
            Vector3D dir = c.LookDirection;
            dir.Normalize();

            Vector3D right = Vector3D.CrossProduct(dir, c.UpDirection);
            right.Normalize();

            const double d = 0.5;

            var q1 = new Quaternion(-up, d * dx);
            var q2 = new Quaternion(-right, d * dy);
            Quaternion q = q1 * q2;

            var m = new Matrix3D();
            m.Rotate(q);

            Vector3D newLookDir = m.Transform(c.LookDirection);
            Vector3D newUpDir = m.Transform(c.UpDirection);

            c.LookDirection = newLookDir;
            c.UpDirection = newUpDir;
        }

4-1: I moved current rotation to ALT+left mouse (similar to tools like maya,max,unity)

4-2: I used new rotation function on right mouse, differentiating between both rotations using isFlyRotating

5: Get movement direction based on enum parameter from step 1

        public Vector3D GetDirection(CameraDirection direction)
        {
            // calculate directions
            Vector3D forward = Camera.LookDirection;
            forward.Normalize();

            Vector3D up = Camera.UpDirection;
            up.Normalize();

            Vector3D right = Vector3D.CrossProduct(forward, up);

            // calculate normalized offset
            Vector3D offset = new Vector3D();

            if ((direction & CameraDirection.Forward) == CameraDirection.Forward)
            {
                offset += forward;
            }
            if ((direction & CameraDirection.Backward) == CameraDirection.Backward)
            {
                offset -= forward;
            }

            if ((direction & CameraDirection.Left) == CameraDirection.Left)
            {
                offset -= right;
            }
            if ((direction & CameraDirection.Right) == CameraDirection.Right)
            {
                offset += right;
            }

            if ((direction & CameraDirection.Up) == CameraDirection.Up)
            {
                offset += up;
            }
            if ((direction & CameraDirection.Down) == CameraDirection.Down)
            {
                offset -= up;
            }

            return offset;
        }

6: Add code to start/stop flying

        public void StartFly(CameraDirection direction)
        {
            CameraDirection oldDirection = flyDirection;

            flyDirection |= direction;

            if (oldDirection == CameraDirection.None &&
                flyDirection != CameraDirection.None)
            {
                this.flyIncrement = 0;
            }
        }

        public void StopFly(CameraDirection direction)
        {
            flyDirection &= ~direction;
        }

7: Code to do the flying

        void Fly(double deltaTime)
        {
            const double speedFactor = 40;
            const double shiftSpeedFactor = 5;

            // calculate offset independent of time
            flyIncrement += speedFactor * deltaTime;
            double deltaOffset = flyIncrement * deltaTime;

            if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
            {
                deltaOffset *= shiftSpeedFactor;
            }

            // offset camera
            Camera.Position += GetDirection(flyDirection) * deltaOffset;
        }

8: Call Fly() within OnTimeStep if we have any fly direction

        private void OnTimeStep(double time)
        {
            if (flyDirection != CameraDirection.None)
            {
                Fly(time);
            }
        }

9: Finally add code to start/stop flying based on keypresses

        void Viewport_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            ViewportKeyEvent(e, false);
        }

        void Viewport_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            ViewportKeyEvent(e, true);
        }

        void ViewportKeyEvent(System.Windows.Input.KeyEventArgs e, bool isKeyUp)
        {
            bool isCtrl = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
            bool isAlt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;

            switch (e.Key)
            {
                case Key.Up:
                case Key.W:
                    if (isKeyUp || (!e.IsRepeat && !isCtrl && !isAlt))
                    {
                        Fly(CameraDirection.Forward, isKeyUp);
                    }
                    break;
                case Key.Left:
                case Key.A:
                    if (isKeyUp || (!e.IsRepeat && !isCtrl && !isAlt))
                    {
                        Fly(CameraDirection.Left, isKeyUp);
                    }
                    break;
                case Key.Down:
                case Key.S:
                    if (isKeyUp || (!e.IsRepeat && !isCtrl && !isAlt))
                    {
                        Fly(CameraDirection.Backward, isKeyUp);
                    }
                    break;
                case Key.Right:
                case Key.D:
                    if (isKeyUp || (!e.IsRepeat && !isCtrl && !isAlt))
                    {
                        Fly(CameraDirection.Right, isKeyUp);
                    }
                    break;
                case Key.PageUp:
                case Key.Space:
                    if (isKeyUp || (!e.IsRepeat && !isCtrl && !isAlt))
                    {
                        Fly(CameraDirection.Up, isKeyUp);
                    }
                    break;
                case Key.PageDown:
                case Key.C:
                    if (isKeyUp || (!e.IsRepeat && !isCtrl && !isAlt))
                    {
                        Fly(CameraDirection.Down, isKeyUp);
                    }
                    break;
            }
        }

        void Fly(CameraDirection direction, bool stop)
        {
            if (stop)
            {
                StopFly(direction);
            }
            else
            {
                StartFly(direction);
            }
        }

objo wrote 2013-11-20 at 08:10
cool, I will review this later!

Export to Universal 3D

This issue was imported from CodePlex

objo wrote 2012-12-14 at 07:58
Export to Universal 3D (and PDF 3D).

http://www.ecma-international.org/publications/standards/Ecma-363.htm

http://en.wikipedia.org/wiki/Universal_3D

http://www3.math.tu-berlin.de/jreality/ (BSD)

http://sourceforge.net/projects/u3d/

http://www.okino.com/conv/exp_u3d.htm

Capn_K wrote 2013-07-29 at 05:07
We've done some work on implementing this, by exporting to IDTF and then using the IDTFConvertor to create u3d files, and finally iTextSharp to create the 3d PDF.

Using an IDTF library available from:
https://github.com/CapnK/Duffer and a custom Helix Exporter

objo wrote 2013-09-08 at 09:24
This is interesting, but it would be great to be able to write .u3d directly. I have not checked what compression algorithm is used...

The goal is to write the 3D pdf directly from the WPF3D model.

Capn_K wrote 2013-09-11 at 08:06
I believe that the most maintained u3d library (C++) is
http://www2.iaas.msu.ru/tmp/u3d/u3d-1.4.4.tar.gz which is a repack of the Intel u3d project form Sourceforge.

We wrote to IDTF because (as C# developers) the file format was easier (at first) to understand than the Intel SDK. But, you are correct that it adds a dependency on the IDTFConvertor.exe from sourceforge anyway.

The other option may be to use IKVM.Net + the JReality code (although I didn't look into that).

Once you have a .u3d file, then the code to create a .PDF using iTextSharp is as follows. (Note: This makes the PDF starting view the same as the Helixviewport camera)

        /// 
        /// Create a PDF file by merging a u3d into that file
        /// 
        /// 
        /// 
        ///  The helixviewport to get camera information from
        /// 
        public void CreatePDF(string pdfFilePath, string u3dFilePath, HelixToolkit.Wpf.HelixViewport3D viewport)
        {
            // Create a PDF document
            iTextSharp.text.Document pdfDoc = default(iTextSharp.text.Document);
            pdfDoc = new iTextSharp.text.Document(iTextSharp.text.PageSize.A3.Rotate());

            // Get an PDfWriter 
            System.IO.FileStream pdfFileStream = null;
            pdfFileStream = new System.IO.FileStream(pdfFilePath, System.IO.FileMode.Create);

            iTextSharp.text.pdf.PdfWriter pdfWriter = default(iTextSharp.text.pdf.PdfWriter);
            pdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(pdfDoc, pdfFileStream);

            // Open the document
            pdfDoc.Open();

            // Create rectangle to put the content in 5 unit border all around
            iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(5, 5, pdfDoc.PageSize.Width - 10, pdfDoc.PageSize.Height - 10);
            rect.Border = Rectangle.BOX;
            rect.BorderWidth = 0.5F;
            rect.BorderColor = new BaseColor(System.Drawing.Color.LightGray);
            pdfDoc.Add(rect);

            // Create stream in PDF to contain 3d data
            System.IO.FileStream u3dStream = new System.IO.FileStream(u3dFilePath, System.IO.FileMode.Open);
            iTextSharp.text.pdf.PdfStream stream3d = new iTextSharp.text.pdf.PdfStream(u3dStream, pdfWriter);
            stream3d.Put(PdfName.TYPE, new PdfName("3D"));
            stream3d.Put(PdfName.SUBTYPE, new PdfName("U3D"));
            stream3d.FlateCompress();
            PdfIndirectObject streamObject = pdfWriter.AddToBody(stream3d);
            stream3d.WriteLength();

            PdfDictionary dict3d = new PdfDictionary();
            dict3d.Put(PdfName.TYPE, new PdfName("3DView"));
            dict3d.Put(new PdfName("XN"), new PdfName("Default"));
            dict3d.Put(new PdfName("IN"), new PdfName("Unnamed"));
            dict3d.Put(new PdfName("MS"), PdfName.M);
            //viewport.Camera.Position
            var pdfArrayValues = CalculateViewTransform(viewport);

            //FIXME - The view is still zoomed in a bit too far when compared to the original Helixviewport
            // Shortnening the CO length didn't seem to make any difference

            dict3d.Put(new PdfName("C2W"), new PdfArray(pdfArrayValues.ToArray()));
            dict3d.Put(PdfName.CO, new PdfNumber(viewport.Camera.LookDirection.Length));
            PdfIndirectObject dictObject = pdfWriter.AddToBody(dict3d);


            PdfAnnotation annotation = new PdfAnnotation(pdfWriter, rect);
            annotation.Put(PdfName.CONTENTS, new PdfString("3D model"));
            annotation.Put(PdfName.SUBTYPE, new PdfName("3D"));
            annotation.Put(PdfName.TYPE, PdfName.ANNOT);
            annotation.Put(new PdfName("3DD"), streamObject.IndirectReference);
            annotation.Put(new PdfName("3DV"), dictObject.IndirectReference);

            PdfAppearance pdfAppear = pdfWriter.DirectContent.CreateAppearance(rect.Width, rect.Height);
            annotation.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, pdfAppear);
            annotation.SetPage();

            pdfWriter.AddAnnotation(annotation);

            //pdfDoc.Add(New iTextSharp.text.Paragraph("Hellow World!"))

            pdfDoc.Close();

        }

        private static List CalculateViewTransform(HelixViewport3D viewport)
        {
            var pdfArrayValues = new List(12); // {1, 0, 0, 0, 0, -1, 0, 1, 0, 3, -235, 28 };

            PerspectiveCamera pc = viewport.Camera as PerspectiveCamera;

            var zAxis = pc.LookDirection;
            var yAxis = pc.UpDirection;  //UpDirectiosn seems to be World up, not perp to LookDirection
            var xAxis = Vector3D.CrossProduct(zAxis, yAxis);
            yAxis = Vector3D.CrossProduct(xAxis, zAxis); //make sure y is perp to x and z

            xAxis.Normalize();
            yAxis.Normalize();
            zAxis.Normalize();

            pdfArrayValues.Add((float)xAxis.X);
            pdfArrayValues.Add((float)xAxis.Y);
            pdfArrayValues.Add((float)xAxis.Z);

            pdfArrayValues.Add((float)yAxis.X);
            pdfArrayValues.Add((float)yAxis.Y);
            pdfArrayValues.Add((float)yAxis.Z);

            pdfArrayValues.Add((float)zAxis.X);
            pdfArrayValues.Add((float)zAxis.Y);
            pdfArrayValues.Add((float)zAxis.Z);

            pdfArrayValues.Add((float)viewport.Camera.Position.X);
            pdfArrayValues.Add((float)viewport.Camera.Position.Y);
            pdfArrayValues.Add((float)viewport.Camera.Position.Z);
            return pdfArrayValues;
        }

Capn_K wrote 2013-09-11 at 08:11
I should have said "most maintained open-source library is
http://www2.iaas.msu.ru/tmp/u3d/"

Obviously others like Okino, PDF3d SDK, Tetra4d and other commercial options exist....

Selection by 3D box

This issue was imported from CodePlex

rinaldin wrote 2013-10-29 at 16:47
add a new method to select in which FrameworkElements the event element.MouseDown has raised, after the user draw a box on screen (using Ray3D?)

3ds import problem

This issue was imported from CodePlex

jpg99 Aug 15, 2012 at 4:19 PM

i use your class StudioReader to import 3ds files. Most of the time the result is very good, but at several occasions i encountered files that were incorrectly imported.

I don't have 3d studio max, i use the freeware 3D Object Converter to test the 3ds files. And i use your sample application, 3D model viewer, to see 'your' version of the file.

I import house models from the site archive3d.net . It's all free and i know that quality is not guaranteed. For example when reading http://archive3d.net/?a=download&id=599a4f07 , 3D Object Converter warns that 40 bad polygons were found. And indeed when viewing the result there are clearly errors

But in some cases the 3ds file is correctly displayed in 3D Object Converter, but not in your 3D model viewer : http://archive3d.net/?a=download&id=e190fe70

objo wrote 2012-08-24 at 09:50
See
http://helixtoolkit.codeplex.com/discussions/391696

Zoom to extents in orthographic mode changes field of view in perspective mode.

This issue was imported from CodePlex

AnotherBor wrote 2014-01-09 at 11:10
Draw a scene using perspective camera.

Set FOV to 45.

Zoom to extents (by using HelixViewport3D.ZoomExtents(...)).

  1. Switch to orthographic mode (by setting HelixViewport3D.Orthographic = true;).
  2. Zoom in (mouse wheel).
  3. Zoom to extents (by using HelixViewport3D.ZoomExtents(...)).
  4. Switch to perspective mode (by setting HelixViewport3D.Orthographic = false;).

Now FOV > 45.

Change of FOV after switching to perspective mode depends on amount of zooming-in while in orthographic mode.

objo wrote 2014-02-17 at 08:24
It would be nice to have a unit test for this!

Cutting to solid 3D models

This issue was imported from CodePlex

rohitrpaswan wrote 2013-10-16 at 15:52
i need to cut 3D models using CuttingPlaneGroup.CuttingPlanes. The problem is that i want solid 3D models. But the models are not really solid(they are not filled inside). How can i achieve that??

Thank you

ContourFacet is missing some segments

Hi,
I think the "ContourFacet" method is not handling some cases;
1 - One of the points is on the cutting plane and the other points are on the opposite sides.
2 - Two of the points are on the cutting plane and third point is on either side.
When these conditions apply the contour segment is ignored. I kind of fixed this but ithe code came out a little bit ugly. And I am not so familiar of concepts like pull request, What should i do? Can you direct me somehow?
Thanks

Specified Visual is already a child of another Visual

This issue was imported from CodePlex

glgweeke wrote 2014-02-05 at 10:36
Hi,

with the latest version of the toolkit i get sometimes the exception :

(„Specified Visual is already a child of another Visual or the root of a CompositionTarget“).

This happens for example, when i add two time a null-Object.

What is the reason for this change.

Why is it now not possible to put two identical objects into the Viewer.

By,

Gregor

TextBillboard sometimes not displaying at all

This issue was imported from CodePlex

Nuriyasov wrote 2012-10-05 at 12:49
When creating many textbillboard objects in the scene, particularly for drawing axis labels, some of the them will not render. This issue is rare and hard to catch. I don't know what it's related to, but labels in my scene are constantly changing: they
change text, they change position and sometimes they are hidden (this meaning the ScaleTransform (0,0,0) is applied). It's pretty impossible to control the issue, as from the programmer's point of view, all the labels in the scene look the same, but in reality,
some (random) may be hidden.

Path finding OBJ Importer

This issue was imported from CodePlex

Rogad wrote 2014-02-04 at 17:45
I noticed that the importer would not find a texture if the relative path is preceded with a slash like this :

newmtl 3_SkinFoot
d 1
Kd 1 1 1
map_Kd /Maps/V5BreeLimbsM.jpg

For the texture to be found I have had to amend it by hand to this :

newmtl 3_SkinFoot
d 1
Kd 1 1 1
map_Kd Maps/V5BreeLimbsM.jpg

ie. Removing the forward slash before 'Maps'.

It would be nice for it to pick up this without having to adjust this by hand each time. I am not sure what the standard is, but the forward slash is generated when I use Daz Studio OBJ Export.

objo wrote 2014-02-04 at 19:29
This should be a one line of code fix :)

But I want a unit test in a pull request solving this issue! Otherwise it will not be accepted :)

Rogad wrote 2014-02-04 at 21:24
Darn, what does that mean ?

goes off to look up unit testing

objo wrote 2014-02-04 at 23:26
You find the unit tests in Source\HelixToolkit.Wpf.Tests\Importers\ObjReaderTests.cs

Rogad wrote 2014-02-05 at 21:37
Is there any documentation on how to do that please ?

I am new to C#, I don't understand what I have to do with that...

objo wrote 2014-02-06 at 05:34
NUnit is documented at http://www.nunit.org/

Increasing the test coverage for the importers has high priority! :)

Add twist through path feature to MeshBuilder.AddTube

This issue was imported from CodePlex

bradphelan wrote 2013-07-09 at 14:48
I've added the ability to twist a section through a path by adding a new parameter
angles to the parameter list. I have also added a parameter
sectionXAxis
which allows you to align the section correctly just like in the
AddExtrudedGeometry method.

In fact I think AddExtrudedGeometry is redundant with the fixes to AddTube below. I've also modified ExtrudedVisual3D.cs to pass on the added parameters.

Should I make a patch to the library with this fix or are there any comments. The code could be added as an overload or as a non backward compatible patch. What do you like?

        /// 
        /// Adds a tube with a custom section.
        /// 
        /// 
        /// A list of points defining the centers of the tube.
        /// 
        /// 
        /// The texture coordinate X values (optional).
        /// 
        /// 
        /// The diameters (optional).
        /// 
        /// 
        /// The section to extrude along the tube path.
        /// 
        /// 
        /// The initial alignment of the xaxis of the section into the
        /// 3D viewport
        /// 
        /// 
        /// The rotation of the section as it moves along the path
        /// 
        /// 
        /// If the tube is closed set to true .
        /// 
        /// 
        /// if set to true [is section closed].
        /// 
        public void AddTube(
            IList path,
            IList angles,
            IList values,
            IList diameters,
            IList section,
            Vector3D sectionXAxis,
            bool isTubeClosed,
            bool isSectionClosed)
        {
            if (values != null && values.Count == 0)
            {
                throw new InvalidOperationException(WrongNumberOfTextureCoordinates);
            }

            if (diameters != null && diameters.Count == 0)
            {
                throw new InvalidOperationException(WrongNumberOfDiameters);
            }

            if (angles != null && angles.Count == 0)
            {
                throw new InvalidOperationException(WrongNumberOfAngles);
            }


            int index0 = this.positions.Count;
            int pathLength = path.Count;
            int sectionLength = section.Count;
            if (pathLength < 2 || sectionLength < 2)
            {
                return;
            }

            var forward = path[1] - path[0];
            var right = sectionXAxis;
            var up = Vector3D.CrossProduct(forward, right);
            up.Normalize();
            right.Normalize();

            int diametersCount = diameters != null ? diameters.Count : 0;
            int valuesCount = values != null ? values.Count : 0;
            int anglesCount = angles != null ? angles.Count : 0;

            for (int i = 0; i < pathLength; i++)
            {
                double radius = diameters != null ? diameters[i % diametersCount] / 2 : 1;
                double theta = angles != null ? angles[i % anglesCount] : 0.0;

                double ct = Math.Cos(theta);
                double st = Math.Sin(theta);

                int i0 = i > 0 ? i - 1 : i;
                int i1 = i + 1 < pathLength ? i + 1 : i;

                forward = path[i1] - path[i0];
                right = Vector3D.CrossProduct(up, forward);
                up = Vector3D.CrossProduct(forward, right);
                up.Normalize();
                right.Normalize();
                for (int j = 0; j < sectionLength; j++)
                {
                    var x = section[j].X * ct - section[j].Y * st ;
                    var y = section[j].X * st + section[j].Y * ct;

                    var w = (x * right * radius) + (y * up * radius);
                    var q = path[i] + w;
                    this.positions.Add(q);
                    if (this.normals != null)
                    {
                        w.Normalize();
                        this.normals.Add(w);
                    }

                    if (this.textureCoordinates != null)
                    {
                        this.textureCoordinates.Add(
                            values != null
                                ? new Point(values[i % valuesCount], (double)j / (sectionLength - 1))
                                : new Point());
                    }
                }
            }

            this.AddRectangularMeshTriangleIndices(index0, pathLength, sectionLength, isSectionClosed, isTubeClosed);
        }

bradphelan wrote 2013-07-09 at 15:28
Added pull request at

https://helixtoolkit.codeplex.com/SourceControl/network/forks/bradphelan/doublehelix/contribution/5033

objo wrote 2013-07-12 at 23:15
Great! I will look at this after the vacation!

View cube features

This issue was imported from CodePlex

objo wrote 2012-06-09 at 22:47
Each of edge, corner and side of cube can change type of view. And most important, after turning you can see at least 2-3 sides of cube.

(moved from issue 9953)

LinesVisual3D Buggy

This issue was imported from CodePlex

freethinker wrote 2012-06-27 at 22:01
The LinesVisual3D doesn't render flawlessly. You can clearly see in this picture that the 'billboards' aren't working too great leaving less than satisfying visuals.

Code used:

        Point3DCollection pts = new Point3DCollection();

        for (int w = 0; w < 32; w++)
        {
            pts.Add(new Point3D(w * 1, 0, 0));
            pts.Add(new Point3D(w * 1, 32, 0));
        }

        for (int h = 0; h < 32; h++)
        {
            pts.Add(new Point3D(0, h * 1, 0));
            pts.Add(new Point3D(32, h * 1, 0));
        }

        LinesVisual3D ln = new LinesVisual3D();
        ln.Points = pts;
        ln.Color = Colors.White;
        this.MainViewport.Children.Add(ln);

objo wrote 2012-06-28 at 06:57
There might be some numerical issues in the implementation, but I think this is a problem that might be hard to solve in WPF3D.

Please check 3DTools and Petzold's screen space line implementations, if they work better!

Also, I think other 3D platforms than WPF3D should be considered if rendering lines is important!

freethinker wrote 2012-06-29 at 00:26
Indeed, I found those libraries shortly after, they seem to work better (though not perfect either). Hopefully WPF 5 will bring some more life into Media.3D.

Great Library by the way. Thanks.

Refactoring of exporters

This issue was imported from CodePlex

objo wrote 2014-02-14 at 15:49
should use the following pattern:

var exporter = new ObjExporter();
using (var stream = File.Create(path))
{
    exporter.Export(viewport, stream);
}

BillboardTextVisual3D calculates wrong bounds

This issue was imported from CodePlex

survivorx wrote 2013-09-25 at 11:50
BillboardTextVisual3D calculates wrong bounds. You can see this by repeatedly clicking on ZoomExtents(). The focused scene will get smaller and smaller with every click. It has something to do with BillboardTextVisual3D.DepthOffset. Maybe some screen space
issue. My workaround is to ignore BillboardTextVisual3D in Visual3DHelper.FindBounds().

ViewPort3DHelper.FindHits calculates wrong distance

This issue was imported from CodePlex

jtu100 wrote 2013-11-21 at 07:04
I have the following VisualTree:

  • Viewport
    • ModelVisual3D.Content
      • ModelGroup3D
        • GeometryModel3D
I have a grid of cubes (10 x 10) plus a quad they are sitting on top of (and bounded by), for a total of 101 GeometryModel3D.

No transforms are applied except to the cubes, where I am using a TranslateTransform3D on their GeometryModel3D.

The cube in the top right is translated by 50,50,0 so is rendered in the top right.

The problem is if I call FindHits on this top right cube I will get the quad returned as the closest object even thought its actually the cube. The problem appears to be this function:

       private static Point3D GetGlobalHitPosition(RayHitTestResult rayHit, Viewport3D viewport)
        {
            var p = rayHit.PointHit;

            // first transform the Model3D hierarchy
            var t2 = rayHit.VisualHit.GetTransformTo(rayHit.ModelHit);
            if (t2 != null)
            {
                p = t2.Transform(p);
            }

            // then transform the Visual3D hierarchy up to the Viewport3D ancestor
            var t = GetTransform(viewport, rayHit.VisualHit);
            if (t != null)
            {
                p = t.Transform(p);
            }

            return p;
        }

I may be wrong but the rayHit.PointHit is already in Visual3D space (in my case the untransformed ModelVisual3D)...but this code tries to transforms the coordinate from model space to visual space, even thought its already in visual space?? In my case this
results in "position" for the top right cube being at 100,100 instead of 50,50 so it deemed as being further from the camera and hence the quad is reported as closest.

See framework source code RayMeshGeometry3DHitTestResult.cs ... comment on PointHit "This point is in the coordinate system of the Visual3D"

jtu100 wrote 2013-12-04 at 01:37
I have submitted a patch for this

objo wrote 2013-12-04 at 07:10
Thanks for the reminder. I will submit the change, but I would also like to include a unit test to verify that the calculation is correct before closing the issue!

jtu100 wrote 2014-07-12 at 20:39
Has this been integrated into the mainline now?

jtu100 wrote 2014-07-12 at 20:41
Oh yes I see that it has. Commit f885ee4cad75

CuttingPlaneGroup: visible planes and manipulators

This issue was imported from CodePlex

etick wrote 2013-02-18 at 13:40
When using the Plane3D function on a loaded 3DS model, objects are still shown on the screen.

Would be nice that the cutting plane can show a rectangle or transparent.

Also a option to move it would be great.

objo wrote 2013-04-15 at 12:36
I would prefer to bind the planes to other Visual3D objects, otherwise a lot of properties may be duplicated (width, height, fill color, frame color, orientation of the plane, which manipulators to enable (translate, rotate) etc.).

etick wrote 2013-04-25 at 16:18
As i understand all these objects must be in the CuttingPlaneGroup, can you please elaborate how this can be done.

I can move the planes that cut the objects but how can i bind it to a rectangle of some sort that displays the cutting plane ?

objo wrote 2013-04-26 at 22:09
I think some refactoring of the implementation of the CuttingPlanes property is necessary here...

The CuttingPlanes property should be an observable collection, the cutting plane objects should be DependencyObjects, and added to the visual tree (to allow binding, but without any visible geometry)

Portable library (refactoring)

Move mesh builder, camera manipulation, exporters and importers to a portable class library (PCL).

It should be possible to use this on library on different visualization platforms (e.g. WPF, SharpDX, OpenGL).

Change ViewBox to some other shape

This issue was imported from CodePlex

chadsixt wrote 2013-09-13 at 22:28
Is there a way to change the ViewCube to something else. I am developing a medical application and wanted to change the cube to a human torso. Is that possible?

Obj export doesn't export correct transform/rotation

This issue was imported from CodePlex

AlexanderPD wrote 2013-03-30 at 12:59
Hi, i'm exporting my model with a normal

exporter.Export(Model);

My Model is a Model3DGroup with some Children, every Children has a custom Transform3DGroup.

Every Transform3DGroup has different transform and rotate value (saved as childs of that Transform3DGroup).

When i import the exported model transform and rotation values are different from the model in viewport! Rotation seems to be resetted and transform set some model in different places (seems like only 1 axis is wrong)

The global model is also rotated and transformed but fix it manually during the obj load.

Can you fix those bugs?

Thank you all for your great work, Helix 3D Toolkit rocks!

objo wrote 2013-04-15 at 12:31
Can you create some code (preferably a unit test) that reproduces this error?

The "ExportDemo" in the "ExampleBrowser" creates an .obj file with a hierarchy of transformed groups. I verified this in Octane render when I created the example, but I see MeshLab has problems importing the file...

Attached property for names of Visual3Ds

This issue was imported from CodePlex

objo wrote 2013-09-08 at 08:48
Create an attached property to use for names

[discussion:451810]

Exporters that support named objects and groups should use this attached property.

objo wrote 2013-09-08 at 09:20
I have added the attached properties. I have not implemented changes to the exporters.

RobPerkins wrote 2013-09-09 at 17:29
Shouldn't exporters which can do this exploit the "x:Name" attached property found in the
http://schemas.microsoft.com/winfx/2006/xaml namespace, rather than creating a new one altogether?

objo wrote 2013-09-09 at 18:05
Is this possible? I could not get the standard FrameworkElement.NameProperty to work with Visual3D/Model3D dependency objects. Can we override the metadata?

RobPerkins wrote 2013-09-10 at 21:38
I don't think FrameworkElement.NameProperty is the same as the canonical "x:Name" in all the XAML examples, even though both give you a variable name for code behind. And Visual3D and Model3D don't descend from FrameworkElement... hmm...

Your implementation looks straightforward enough; it attaches a NameProperty to both DispatcherObject classes. So, we'd use it by doing ?

objo wrote 2013-09-10 at 22:08
<h:SomeHelixModel3DClass h:Model3DPr.Name="myName"/>

The idea is that this property could be used by importers and exporters.

It should also be possible to set names of Materials.

Capn_K wrote 2013-09-11 at 04:01
'Name' is very specific to that Visual3d/Model3d element

I was thinking more along the lines of 'Group' or 'Layer'.

But then that is because my use case would be to use it as a way of group elements so they could potentially be added/removed form the viewport to turn them on/off.

And Visual3d's with the same Name/Group/Layer would be exported to different groups/layers (e.g. obj supports groups, and I'm working with IDTF which also supports a similar concept)

RobPerkins wrote 2013-09-11 at 19:25
Objo, what I've learned looking into this is that FrameworkElement maps its "NameProperty" to the x:Name XAML element, making the two interchangable for FrameworkElement and all its derived classes. So the scope of my suggestion gets a little
incoherent in light of that.

However, it might be possible to define a mapping for Model3Dpr.Name and your other attached properties to the XAML x:Name element so that the declaration becomes more or less seamless, as with FrameWorkElement. Or, if the Helix classes have a common base class
which derives from Visual3D, Model3D, Geometry3D, etc, you could simply define a NameProperty and do that mapping, somehow.

Alas, I don't actually know how to do that part.

As to Capn_K's idea, I like the notion of an attached property called "Group" or "Layer". You could define it to attach to DependencyObject, which would let it cover all the possibilities.

objo wrote 2013-09-11 at 20:40
Yes, I guess it is ok to set DependencyObject as owner type! I still like to use "Name" - it does not make much sense to use "Layer" for a material? See the code I just checked in.

RobPerkins wrote 2013-09-12 at 00:36
Does this reduce the XAML code to something like

 h:Name="TheName"

?

objo wrote 2013-09-12 at 06:33
h:AttachedProperties.Name="TheName"

Attached property to show/hide Visual3Ds

This issue was imported from CodePlex

objo wrote 2013-09-29 at 09:31
Add an attached property to show/hide Visual3Ds and Model3Ds

When hiding:

ModelVisual3D

ContainerUIElement3D

ModelUIElement3D

remove from the parent's Children collection

Model3D

if parent is a ModelVisual3D - remove it from parent's Content

if parent is a Model3DGroup - remove it from parent's Children

When removing from collections - add an empty placeholder in the collection (and make it thread safe)

Store old parents and placeholders in temporary attached properties

https://helixtoolkit.codeplex.com/workitem/10000

survivorx wrote 2013-09-29 at 11:34
I'll contribute this.

For GeometryModel3D we need a different solution using a dictionary because it's not a DependencyObject.

survivorx wrote 2013-09-29 at 12:46
Ok, after really looking at this I must admit I wrongly assumed Visual3D or ModelVisual3D had a Material property, but it's a property of BillboardVisual3D (and probably other Helix classes). So there is no easy general solution using Material.

A better solution might be disconnecting the Content from the Visual3D. This would affect the properties Visual3D.Visual3DModel (protected, reflection needed), ModelVisual3D.Children and ModelVisual3D.Content.

survivorx wrote 2013-09-30 at 17:15
Here is a solution for ModelGeometry3D using Material:

namespace Common
{
  using System.Windows;
  using System.Windows.Media.Media3D;

  public class Visibility3D : DependencyObject
  {
    public static readonly DependencyProperty IsHiddenProperty =
      DependencyProperty.RegisterAttached(
        "IsHidden", typeof(bool), typeof(Visibility3D), new PropertyMetadata(false, IsHiddenChangedCallback));

    private static readonly DependencyProperty HiddenMaterialProperty =
      DependencyProperty.RegisterAttached(
        "HiddenMaterial", typeof(Material), typeof(Visibility3D), new UIPropertyMetadata(null));

    private static readonly DependencyProperty HiddenBackMaterialProperty =
      DependencyProperty.RegisterAttached(
        "HiddenBackMaterial", typeof(Material), typeof(Visibility3D), new UIPropertyMetadata(null));

    static Visibility3D()
    {
      GeometryModel3D.MaterialProperty.OverrideMetadata(typeof(Visibility3D), new PropertyMetadata(null, null, CoerceMaterialCallback));
      GeometryModel3D.BackMaterialProperty.OverrideMetadata(typeof(Visibility3D), new PropertyMetadata(null, null, CoerceBackMaterialCallback));
    }

    public static bool GetIsHidden(DependencyObject d)
    {
      return (bool)d.GetValue(IsHiddenProperty);
    }

    public static void SetIsHidden(DependencyObject d, bool value)
    {
      d.SetValue(IsHiddenProperty, value);
    }

    private static void IsHiddenChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      var geom = (GeometryModel3D)d;
      if ((bool)e.NewValue)
      {
        geom.SetValue(HiddenMaterialProperty, geom.Material);
        geom.SetValue(HiddenBackMaterialProperty, geom.BackMaterial);
        geom.Material = null;
        geom.BackMaterial = null;
      }
      else
      {
        geom.Material = (Material)geom.GetValue(HiddenMaterialProperty);
        geom.BackMaterial = (Material)geom.GetValue(HiddenBackMaterialProperty);
        geom.ClearValue(HiddenMaterialProperty);
        geom.ClearValue(HiddenBackMaterialProperty);
      }
    }

    private static object CoerceMaterialCallback(DependencyObject d, object baseValue)
    {
      var geom = (GeometryModel3D)d;
      if ((bool)geom.GetValue(IsHiddenProperty))
      {
        d.SetValue(HiddenMaterialProperty, baseValue);
        return null;
      }

      return baseValue;
    }

    private static object CoerceBackMaterialCallback(DependencyObject d, object baseValue)
    {
      var geom = (GeometryModel3D)d;
      if ((bool)geom.GetValue(IsHiddenProperty))
      {
        d.SetValue(HiddenBackMaterialProperty, baseValue);
        return null;
      }

      return baseValue;
    }
  }
}

You can bind it to a ToggleButton like this:

How to get target location in mouse move?

I created a big terrain using AddRectangularMesh(). If I double right click then the camera's target position is changed. Is there any way to show the target points in mouse move event.

Basically I want to show the height of the terrain where the mouse pointer is pointed

Problems with HelixViewport3D

This issue was imported from CodePlex

amine28 wrote 2013-06-01 at 21:11
Hello, many thanks for the toolkit that you've built.

I am facing problems conserning HelixViewport3D i can't add the control to the visual studio toolbox and have the following message => there are no compnents in ....\helixtoolkit.wpf.dll that can be palced on the toolbox.

objo wrote 2013-06-11 at 04:43
what version of VS do you use?

It works in VS 2012: right click in Toolbox -> choose items -> browse..

The controls are listed under "Common WPF Controls"

Default zoom in XPS

This issue was imported from CodePlex

udaykm1986 wrote 2013-09-18 at 09:14
When we create XPS document with HelixViewport3D then the content of viewport appears very big and UI is getting cropped in the document. How to solve this issue?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.