public MainWindow() { InitializeComponent(); cubit = new CubeVisual3D { SideLength = a * b, Fill = Brushes.SandyBrown }; Loaded += this.MainWindowLoaded; }
public Element() { Tube = new TubeVisual3D(); Tube.Path = new Point3DCollection(); Tube.Path.Add(new Point3D(-15, 0, 0)); Tube.Path.Add(new Point3D(15, 0, 0)); Tube.Diameter = tubeDiameter; Tube.IsSectionClosed = true; Tube.Fill = new SolidColorBrush(Colors.Silver); Tube.IsPathClosed = false; Sphere = new CubeVisual3D(); //Sphere.Center = new Point3D(15, 0, 0); Sphere.Fill = new SolidColorBrush(Colors.Silver); Sphere.SideLength = 0.75; }
private void InitializeHelix() { _helixItems.Add(new SunLight()); _helixItems.Add(new GridLinesVisual3D { Width = 500, Length = 500 }); foreach (CameraModel cameraModel in Cameras) { CubeVisual3D cube = new CubeVisual3D(); cube.SideLength = 10; cube.Fill = new SolidColorBrush(Colors.Blue); cube.Center = new Point3D(cameraModel.Calibration.TranslationToWorld[0, 0], cameraModel.Calibration.TranslationToWorld[2, 0], cameraModel.Calibration.TranslationToWorld[1, 0]); _helixItems.Add(cube); } if (Cameras.Count == 4) { ArrowVisual3D arrow = new ArrowVisual3D { Point1 = new Point3D( GetCamera(0).Calibration.TranslationToWorld[0, 0], GetCamera(0).Calibration.TranslationToWorld[2, 0], GetCamera(0).Calibration.TranslationToWorld[1, 0]), Point2 = new Point3D( GetCamera(2).Calibration.TranslationToWorld[0, 0], GetCamera(2).Calibration.TranslationToWorld[2, 0], GetCamera(2).Calibration.TranslationToWorld[1, 0]), Fill = new SolidColorBrush(Colors.Yellow) }; _helixItems.Add(arrow); arrow = new ArrowVisual3D { Point1 = new Point3D( GetCamera(1).Calibration.TranslationToWorld[0, 0], GetCamera(1).Calibration.TranslationToWorld[2, 0], GetCamera(1).Calibration.TranslationToWorld[1, 0]), Point2 = new Point3D( GetCamera(3).Calibration.TranslationToWorld[0, 0], GetCamera(3).Calibration.TranslationToWorld[2, 0], GetCamera(3).Calibration.TranslationToWorld[1, 0]), Fill = new SolidColorBrush(Colors.Yellow) }; _helixItems.Add(arrow); } ArrowVisual3D axis = new ArrowVisual3D { Origin = new Point3D(0, 0, 0), Direction = new Vector3D(100, 0, 0), Diameter = 2, Fill = new SolidColorBrush(Colors.Red) }; _helixItems.Add(axis); axis = new ArrowVisual3D { Origin = new Point3D(0, 0, 0), Direction = new Vector3D(0, 100, 0), Diameter = 2, Fill = new SolidColorBrush(Colors.Green) }; _helixItems.Add(axis); axis = new ArrowVisual3D { Origin = new Point3D(0, 0, 0), Direction = new Vector3D(0, 0, 100), Diameter = 2, Fill = new SolidColorBrush(Colors.Blue) }; _helixItems.Add(axis); }
private void InitializeHelix() { _items.Clear(); _controllerObjects = new ObservableConcurrentDictionary<MotionControllerModel, SphereVisual3D>(); _items.Add(new SunLight()); _items.Add(new GridLinesVisual3D { Width = 500, Length = 500 }); CubeVisual3D camera = new CubeVisual3D { SideLength = 10, Fill = new SolidColorBrush(Colors.Blue), Center = new Point3D(_camera.Calibration.TranslationToWorld[0, 0], _camera.Calibration.TranslationToWorld[2, 0], _camera.Calibration.TranslationToWorld[1, 0]) }; _items.Add(camera); ArrowVisual3D axis = new ArrowVisual3D { Origin = new Point3D(0, 0, 0), Direction = new Vector3D(100, 0, 0), Diameter = 2, Fill = new SolidColorBrush(Colors.Red) }; _items.Add(axis); axis = new ArrowVisual3D { Origin = new Point3D(0, 0, 0), Direction = new Vector3D(0, 100, 0), Diameter = 2, Fill = new SolidColorBrush(Colors.Green) }; _items.Add(axis); axis = new ArrowVisual3D { Origin = new Point3D(0, 0, 0), Direction = new Vector3D(0, 0, 100), Diameter = 2, Fill = new SolidColorBrush(Colors.Blue) }; _items.Add(axis); }
public World() { // instantiate our world WorldObjects = new ModelVisual3D(); Cubes = new ModelVisual3D(); JointObjects = new ModelVisual3D(); // create something to represent where the kinect is Kinect = new CubeVisual3D() { SideLength = 0.1, Center = new Point3D(0, 0, 0), Material = MaterialHelper.CreateMaterial(_Constants.KinectBrush, _Constants.KinectBrush) }; // something to represent the floor RectangleVisual3D Floor = new RectangleVisual3D() { LengthDirection = new Vector3D(0, 0, 1), Normal = new Vector3D(0, 1, 0), Origin = new Point3D(0, -0.01, 0), Length = 20, Width = 20, Fill = Brushes.White, Material = MaterialHelper.CreateMaterial(Brushes.White, Brushes.White) }; WorldObjects.Children.Add(Floor); // grid lines to layer on top of the floor GridLines = new GridLinesVisual3D() { LengthDirection = new Vector3D(0, 0, 1), Normal = new Vector3D(0, 1, 0), Transform = new ScaleTransform3D(0.025, 0.025, 0.025), Center = new Point3D(0, 0, 100), }; WorldObjects.Children.Add(GridLines); // and a reference co-ordinate system CoordinateSystem = new CoordinateSystemVisual3D() { ArrowLengths = 0.3 }; WorldObjects.Children.Add(CoordinateSystem); // setup our world transformations FloorTransform = new TranslateTransform3D(); AngleRotationTransform = new RotateTransform3D(Rotation3D.Identity, Kinect.Center); WorldTransforms = new Transform3DGroup(); WorldTransforms.Children.Add(FloorTransform); WorldTransforms.Children.Add(AngleRotationTransform); Kinect.Transform = WorldTransforms; JointObjects.Transform = FloorTransform; }
/// <summary> /// Tick the engine. Usually gets called by the kinect when AllFramesReady fires /// </summary> public void Tick(object sender, SkeletonFrameReadyEventArgs e) { // first thing we want to do is check if the kinect and all our objects // are valid // if there's no kinect, we need to forcibly denotify everything // and throw an exception if (Kinect == null || !Kinect.IsRunning) { DenotifyEverything(); throw new NoKinectException(); } SkeletonFrame skeletonFrame = e.OpenSkeletonFrame(); // now is where we put any pre-conditions of the objects if ( skeletonFrame == null // no skeleton data || JointsToTrack == null // nothing has been specified to track || JointsToTrack.Count == 0 ) return; // get the f**k outta here // bring in our skeletons Skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo(Skeletons); // re-arrange our world according to parameters from the kinect // such as where it thinks the floor is //if (skeletonFrame.FloorClipPlane.Item4 != 0) // World.SetFloorHeight(skeletonFrame.FloorClipPlane.Item4); // and the angle the kinect is lookint at // stabilise our angles by picking the median from a set of angle samples floorStabilisationAngles[currentFloorStabilisationAngleIndex++] = Kinect.ElevationAngle; if (currentFloorStabilisationAngleIndex == _Constants.FloorStabilisationSamples) { World.SetKinectAngle((float)_Math.GetMedian(floorStabilisationAngles)); currentFloorStabilisationAngleIndex = 0; // adjust the camera view so it shows out from the kinect Viewport3D.Camera.Position = World.Kinect.Center; Viewport3D.Camera.LookDirection = new Vector3D(0, 0, 1); Viewport3D.Camera.Transform = World.FloorTransform; } // denotify any cubes that are associated with skeletons that no longer exist List<int> skeletonsToNuke = new List<int>(); foreach (int skeletonTrackingId in DenotifyQueue.Keys) { // if it exists in this new list of skeletons, fine bool exists = false; foreach (Skeleton skeleton in Skeletons) if (skeleton.TrackingId == skeletonTrackingId) exists = true; // if it doesnt, denotify its arse off // and remove the joint geometry too if (!exists) { foreach (JointType jointType in DenotifyQueue[skeletonTrackingId].Keys) { foreach (Cube cube in DenotifyQueue[skeletonTrackingId][jointType]) cube.DeNotify(); World.JointObjects.Children.Remove(Joint3DGeometry[skeletonTrackingId][jointType]); } skeletonsToNuke.Add(skeletonTrackingId); } } foreach (int skeletonToNuke in skeletonsToNuke) DenotifyQueue.Remove(skeletonToNuke); // ok at this point we should be all stable and ready to do operations if (Mode != EngineMode.NoInteractive) { // first thing we need to do is register our skeletons & joints // and sort out their reference 3d geometry // for each skeleton bool firstSkeleton = true; foreach (Skeleton skeleton in Skeletons) { // only track full skeletons that we can find (will be 2 - all the API supports) if (skeleton != null && skeleton.TrackingState == SkeletonTrackingState.Tracked) { // initialise this skeleton if we need to if (!DenotifyQueue.ContainsKey(skeleton.TrackingId)) DenotifyQueue.Add(skeleton.TrackingId, new Dictionary<JointType, List<Cube>>()); // initialise it // and the joint geometry if we need to if (!Joint3DGeometry.ContainsKey(skeleton.TrackingId)) Joint3DGeometry.Add(skeleton.TrackingId, new Dictionary<JointType, CubeVisual3D>()); // for each jointType foreach (JointType jointType in JointsToTrack) { // check its being tracked by the skeleton tracker if (skeleton.Joints[jointType].TrackingState != JointTrackingState.NotTracked) { // transform the location of this joint to something more useful Point3D jointLocation = _3DUtil.Joint3DGeometryToPoint3D(skeleton.Joints[jointType].Position); jointLocation.X = -jointLocation.X; // initialise in our denotify queue if (!DenotifyQueue[skeleton.TrackingId].ContainsKey(jointType)) DenotifyQueue[skeleton.TrackingId].Add(jointType, new List<Cube>()); // initialise it // create some geometry for the joint if necessary (to visualise) if (!Joint3DGeometry[skeleton.TrackingId].ContainsKey(jointType)) { CubeVisual3D cube = new CubeVisual3D() { SideLength = _Constants.JointRadius, Center = jointLocation, Material = MaterialHelper.CreateMaterial(_Constants.JointBrush, _Constants.JointBrush) }; Joint3DGeometry[skeleton.TrackingId].Add(jointType, cube); World.JointObjects.Children.Add(cube); } // Move the joint representation geometry Joint3DGeometry[skeleton.TrackingId][jointType].Center = jointLocation; // adjust the joint geometry because of the world transform jointLocation.Y += World.FloorHeight; // now go through our notification queue // only do this if we are in normal interaction mode if (Mode == EngineMode.NormalInteractive) { // if the point of this joint is in a cube foreach (Cube cube in Cubes) { if (cube.ModelVisual3D.Content.Bounds.Contains(jointLocation)) { // and the cube is not already notified (if someone hasnt already stuck their limb in there) if (!cube.Notified) { // notify it, and add it to the list of things to denotify for this skeleton and joint type DenotifyQueue[skeleton.TrackingId][jointType].Add(cube); cube.Notify(); } else { // delays detection by a frame, but makes the program more efficient AnalogueCube analogueCube = cube as AnalogueCube; if (analogueCube != null) { // if its an analogue cube we have to always notify with the // relative x position Rect3D cubeRect = cube.ModelVisual3D.Content.Bounds; Point3D cubeCenter = new Point3D( cubeRect.X + cubeRect.SizeX / 2d, cubeRect.Y + cubeRect.SizeY / 2d, cubeRect.Z + cubeRect.SizeZ / 2d ); ((AnalogueCube)cube).NotifyAnalogue(_3DUtil.UnitDirectionVectorFromPointAToB(cubeCenter, jointLocation)); } } } // otherwise if it exists in the denotify queue for this skeleton and joint, denotify and remove it else { if (DenotifyQueue[skeleton.TrackingId][jointType].Contains(cube)) { cube.DeNotify(); DenotifyQueue[skeleton.TrackingId][jointType].Remove(cube); } } } } } else { // this joint has been marked as not tracked. So we need to denotify all its cubes foreach (Cube cube in DenotifyQueue[skeleton.TrackingId][jointType]) cube.DeNotify(); // kill from our view World.JointObjects.Children.Remove(Joint3DGeometry[skeleton.TrackingId][jointType]); } } // at this point all our joints are guaranteed to have been registered / moved // so now we need to do our CRMD operations // notification of cubes was already disabled if we are in one of these modes (not the interactivenormal mode) // first of all, make sure our pre-requisites are in place // we also only want to do it for the first skeleton if (firstSkeleton) { if (JointsToTrack.Contains(JointType.HandLeft) && JointsToTrack.Contains(JointType.HandRight) && Skeletons.Length > 0) { Point3D leftHandPoint = Joint3DGeometry[skeleton.TrackingId][JointType.HandLeft].Center; Point3D rightHandPoint = Joint3DGeometry[skeleton.TrackingId][JointType.HandRight].Center; Point3D skeletonSpineMidpoint = _3DUtil.Midpoint( _3DUtil.Joint3DGeometryToPoint3D(skeleton.Joints[JointType.ShoulderCenter].Position), _3DUtil.Joint3DGeometryToPoint3D(skeleton.Joints[JointType.HipCenter].Position) ); // check to see whether we should be put into create mode // wait until the hands are crossed for the set period of time if (Mode == EngineMode.NormalInteractive && leftHandPoint.X > rightHandPoint.X) stableTime = DateTime.Now.Ticks; else if ((DateTime.Now.Ticks - stableTime) / TimeSpan.TicksPerMillisecond >= _Constants.CreateStableTimout) { if (createCube != null) { Mode = EngineMode.CreateCube; Debug.WriteLine("Hands are crossed"); ((CubeVisual3D)Joint3DGeometry[skeleton.TrackingId][JointType.HandLeft]).Material = MaterialHelper.CreateMaterial(_Constants.JointBrush, _Constants.JointCreateBrush); ((CubeVisual3D)Joint3DGeometry[skeleton.TrackingId][JointType.HandRight]).Material = MaterialHelper.CreateMaterial(_Constants.JointBrush, _Constants.JointCreateBrush); } } // --old mode // check to see whether we should be put into create mode // wait until the hands are together for the set period of time /*if (Mode == EngineMode.NormalInteractive && _3DUtil.DistanceBetween(leftHandPoint, rightHandPoint) > _Constants.CreateHandDistance * 2.0) stableTime = DateTime.Now.Ticks; else if ((DateTime.Now.Ticks - stableTime) / TimeSpan.TicksPerMillisecond >= _Constants.CreateStableTimout) { if (createCube != null) { Mode = EngineMode.CreateCube; Debug.WriteLine("Hands are together"); } }*/ // now, what we want to do depends on what mode we are in! switch (Mode) { case EngineMode.CreateCube: // only do this stuff if our arms are not crossed (stops bullshit) DenotifyEverything(); if (leftHandPoint.X > rightHandPoint.X) { // move and resize the cube we are creating relative to the hands Point3D cubeCenter = _3DUtil.Midpoint(leftHandPoint, rightHandPoint); cubeCenter.Y += World.FloorHeight; createCube.Resize(_3DUtil.DistanceBetween(leftHandPoint, rightHandPoint)); createCube.MoveTo(cubeCenter); // step 3 // we need to materialise the cube and get out of this process // we do this through a timeout // or TODO: A signal // reset the counter if we fall outside the deadzone if (previousPoint == null || _3DUtil.DistanceBetween(previousPoint, cubeCenter) > _Constants.CreateStableDeadzone) { previousPoint = cubeCenter; stableTime = DateTime.Now.Ticks; } // otherwise if our time has elapsed, materialise the arsehole and leave create mode! else { long currentTime = DateTime.Now.Ticks; // fade colour to joint mode colour // work out percentage of time through the wait period long currentTimeMS = (currentTime - stableTime) / TimeSpan.TicksPerMillisecond; //double currentTimePercent = (double)currentTimeMS / (double)_Constants.CreateStableTimout; if (currentTimeMS >= _Constants.CreateStableTimout) { Debug.WriteLine("timeout, cube is materialised"); OnEngineCubeCreated(new EngineCubeCreatedEventArgs(createCube)); Mode = EngineMode.NormalInteractive; ReorderTransparentObjects(); ((CubeVisual3D)Joint3DGeometry[skeleton.TrackingId][JointType.HandLeft]).Material = MaterialHelper.CreateMaterial(_Constants.JointBrush, _Constants.JointBrush); ((CubeVisual3D)Joint3DGeometry[skeleton.TrackingId][JointType.HandRight]).Material = MaterialHelper.CreateMaterial(_Constants.JointBrush, _Constants.JointBrush); } } } break; case EngineMode.DeleteCube: break; case EngineMode.MoveCube: break; } } firstSkeleton = false; } } } } // drawing of the cubes is handled already // we're a done done! skeletonFrame.Dispose(); }