internal HolofunkState( Clock clock, HolofunkSceneGraph sceneGraph, HolofunkBass bass, HolofunKinect kinect, float initialBPM) { m_clock = clock; m_sceneGraph = sceneGraph; m_bass = bass; m_kinect = kinect; m_requestedBPM = initialBPM; m_player0 = new PlayerModel(0, HolofunkBassAsio.AsioInputChannelId0, this); m_player1 = new PlayerModel(1, HolofunkBassAsio.AsioInputChannelId1, this); }
internal void Update( PlayerHandModel playerModel, HolofunKinect kinect, Moment now) { m_parent.Update(playerModel, kinect, now); bool isDragging = m_model.DragStartLocation.HasValue; Color color = isDragging ? Color.White : new Color(0, 0, 0, 0); // cut alpha of bounding circle m_boundingCircleNode.Color = color * 0.5f; m_effectKnobLineNode.Color = color; m_effectKnobNode.Color = color; if (isDragging) { m_boundingCircleNode.LocalTransform = new Transform(m_model.DragStartLocation.Value, m_boundingCircleNode.LocalTransform.Scale); m_effectKnobLineNode.SetEndpoints(m_model.DragStartLocation.Value, m_model.CurrentKnobLocation.Value); m_effectKnobNode.LocalTransform = new Transform(m_model.CurrentKnobLocation.Value, m_effectKnobNode.LocalTransform.Scale); // TODO: this is a bit inefficient and hacky m_parent.ShowEffectLabels(PlayerEffectSpaceModel.EffectSettings[playerModel.EffectPresetIndex], now); } }
/// <summary>Update the scene's background based on the current beat, and the positions of /// the two hands based on the latest data polled from Kinect.</summary> /// <remarks>We pass in the current value of "now" to ensure consistent /// timing between the PlayerState update and the scene graph udpate.</remarks> internal void Update( HolofunkModel holofunkModel, HolofunKinect kinect, Moment now, float frameRateMsec) { // should do this once a second or so, to reduce garbage... if (++m_frameCount == MagicNumbers.StatusTextUpdateInterval) { m_frameCount = 0; m_statusText.Text.Clear(); long usedAudioMB = Audio.AudioAllocator.TotalReservedSpace / 1024 / 1024; long freeAudioMB = Audio.AudioAllocator.TotalFreeListSpace / 1024 / 1024; long usedVideoMB = holofunkModel.VideoAllocator.TotalReservedSpace / 1024 / 1024; long freeVideoMB = holofunkModel.VideoAllocator.TotalFreeListSpace / 1024 / 1024; m_statusText.Text.AppendFormat( "Time: {10}:{11:D2} | BPM: {0} | Update FPS: {1} | Kinect FPS: {2} | CPU: {3}%\nAudio: {4}/{5}MB | Video: {6}/{7}MB | Free streams: {8}\n{9}\n", Clock.BPM, frameRateMsec == 0 ? 0 : Math.Floor((1000f / frameRateMsec) * 10) / 10, kinect.m_totalFrames / Clock.Now.Seconds, Math.Floor(Audio.CpuUsage * 10) / 10, usedAudioMB - freeAudioMB, usedAudioMB, usedVideoMB - freeVideoMB, usedVideoMB, Audio.StreamPoolFreeCount, (Spam.TopLine1 == null ? "" : Spam.TopLine1) + "\n" + (Spam.TopLine2 == null ? "" : Spam.TopLine2), DateTime.Now.Hour, DateTime.Now.Minute); } // Scale to byte and use for all RGBA components (premultiplied alpha, don't you know) Color backgroundColor = FloatScaleToRGBAColor(1 - (now.FractionalBeat / 1.2f)); m_background.Color = backgroundColor; m_background.SecondaryColor = backgroundColor; m_beatNode.Update(now); Texture2D currentSlide = Content.Slides[holofunkModel.SlideIndex]; m_slide.Texture = currentSlide; m_slide.LocalTransform = new Transform(new Vector2( m_canvasSize.X - (int)(currentSlide.Width), currentSlide.Height / 8)); m_slide.Color = holofunkModel.SlideVisible ? Color.White : new Color(0, 0, 0, 0); Spam.Graphics.WriteLine("EndUpdate"); }
/// <summary>Update the scene's background based on the current beat, and the positions of /// the two hands based on the latest data polled from Kinect.</summary> /// <remarks>We pass in the current value of "now" to ensure consistent /// timing between the PlayerState update and the scene graph udpate.</remarks> internal void Update( PlayerModel playerState, HolofunKinect kinect, Moment now) { m_headGroup.LocalTransform = new Transform( kinect.GetJointViewportPosition(PlayerIndex, JointType.Head) + MagicNumbers.ScreenHandAdjustment, new Vector2(1f)); m_headMikeSignal.Update(now, false, playerState.PlayerColor); m_leftHandSceneGraph.Update(playerState.LeftHandModel, kinect, now); m_rightHandSceneGraph.Update(playerState.RightHandModel, kinect, now); }
internal void Update( PlayerModel playerState, HolofunKinect kinect, Moment now) { }
public void BodyFrameUpdate(HolofunKinect kinect) { // thread-safe operation: snapshot current sample time Moment now = HolofunkModel.Clock.Now; // get the head position Vector2 headPosition = kinect.GetJointViewportPosition(PlayerIndex, Microsoft.Kinect.JointType.Head); // need to find a rectangle centered on headPosition that doesn't cross the viewport edge Rectangle rect = new Rectangle( (int)headPosition.X - MagicNumbers.HeadCaptureSize / 2, (int)headPosition.Y - MagicNumbers.HeadCaptureSize / 2, MagicNumbers.HeadCaptureSize, MagicNumbers.HeadCaptureSize); if (rect.X < 0) { rect.Offset(new Point(-rect.X, 0)); } if (rect.Y < 0) { rect.Offset(new Point(0, -rect.Y)); } if (rect.Right > kinect.ViewportSize.X) { rect.Offset(new Point((int)kinect.ViewportSize.X - rect.Right, 0)); } if (rect.Bottom > kinect.ViewportSize.Y) { rect.Offset(new Point(0, (int)kinect.ViewportSize.Y - rect.Bottom)); } int startOffset = rect.X * 4; if (rect.Y > 0) { startOffset += (rect.Y - 1) * kinect.DisplayTexture.Width * 4; } // if we are recording, get the head position // this method and the regular hand event handling are both called on Kinect thread, // so no need to worry about races on this field lock (m_recorders) { if (m_recorders.Count > 0) { lock (kinect.DisplayTextureBuffer) { // loop from end to start, so we can remove recorders in mid-iteration for (int i = m_recorders.Count - 1; i >= 0; i--) { bool done = m_recorders[i].Record( now.Time, kinect.DisplayTextureBuffer, startOffset, rect.Width * 4, // * 4 because RGBA kinect.DisplayTexture.Width * 4, rect.Height); if (done) { m_recorders.RemoveAt(i); } } } } } }
/// <summary> /// Update this HolofunkBody using the Body state just obtained from the sensor. /// </summary> /// <returns>A tuple of left-hand/right-hand </returns> internal void Update(HolofunKinect kinect, Action<HandPose> leftHandAction, Action<ArmPose> leftArmAction, Action<HandPose> rightHandAction, Action<ArmPose> rightArmAction) { if (m_body == null) { return; } // Save it as it may switch out from under us in response to some actions (e.g. swapping players) Body body = m_body; m_isTracked = body.IsTracked && body.HandLeftState != HandState.NotTracked; m_trackingId = body.TrackingId; if (body.IsTracked) { for (int i = 0; i < JointCount; i++) { JointType id = (JointType)i; Vector2 vp = kinect.GetDisplayPosition(body.Joints[id].Position); m_joints[i].Update(vp); } } // Update the arms. ArmPose leftArmPose = m_leftArm.ArmPose; Option<HandPose> left = m_leftArm.Update(this, body); if (left.HasValue) { leftHandAction(left.Value); } ArmPose rightArmPose = m_rightArm.ArmPose; Option<HandPose> right = m_rightArm.Update(this, body); if (right.HasValue) { rightHandAction(right.Value); } if (leftArmPose != m_leftArm.ArmPose) { leftArmAction(m_leftArm.ArmPose); } if (rightArmPose != m_rightArm.ArmPose) { rightArmAction(m_rightArm.ArmPose); } }
internal void Update(PlayerHandModel playerHandModel, HolofunKinect kinect, Moment now) { // The position adjustment here is purely ad hoc -- the depth image still // doesn't line up well with the skeleton-to-depth-mapped hand positions. m_handGroup.LocalTransform = new Transform( kinect.GetJointViewportPosition( playerHandModel.PlayerModel.PlayerIndex, playerHandModel.IsRightHand ? JointType.HandRight : JointType.HandLeft) + MagicNumbers.ScreenHandAdjustment, new Vector2(MagicNumbers.LoopieScale)); // and make the mike signal update appropriately m_handMikeSignal.Update(now, false, playerHandModel.PlayerModel.PlayerColor); if (m_effectLabelShownMoment.HasValue) { Duration<Sample> elapsed = now.Time - m_effectLabelShownMoment.Value.Time; Color color = new Color(0, 0, 0, 0); if (elapsed > MagicNumbers.EffectLabelFadeDuration) { m_effectLabelShownMoment = Option<Moment>.None; } else { float fraction = 1f - ((float)(long)elapsed / MagicNumbers.EffectLabelFadeDuration); color = Alpha(fraction); } m_effectLabels[0].Color = color; m_effectLabels[1].Color = color; m_effectLabels[2].Color = color; m_effectLabels[3].Color = color; } // Debugging elbow arm pose label. ArmPose armPose = kinect.GetArmPose(m_parent.PlayerIndex, m_isRight ? Side.Right : Side.Left); m_armPoseLabel.Text.Clear(); m_armPoseLabel.Text.Append( armPose == ArmPose.AtChest ? "Chest" : armPose == ArmPose.AtMouth ? "Mouth" : armPose == ArmPose.OnHead ? "Head" : ""); m_armPoseLabel.LocalTransform = new Transform( kinect.GetJointViewportPosition(m_parent.PlayerIndex, m_isRight ? JointType.HandRight : JointType.HandLeft) + new Vector2(0, 50), new Vector2(0.7f)); }
void BodyFrameUpdate(HolofunKinect kinect) { // call into the model to propagate this if (m_model != null) { m_model.BodyFrameUpdate(kinect); } }
/// <summary>Allows the game to perform any initialization it needs to before starting to run.</summary> /// <remarks>This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well.</remarks> protected override void Initialize() { new Test(GraphicsDevice).RunAllTests(); // HORRIBLE HACK: just ensure the statics are initialized string s = PlayerEffectSpaceModel.EffectSettings[0].LeftLabel; m_audioAllocator = new BufferAllocator<float>(2 * 4 * Clock.TimepointRateHz, 128, sizeof(float)); m_holofunkBass = new HolofunkBass(m_clock, m_audioAllocator); m_holofunkBass.StartASIO(); m_kinect = new HolofunKinect(GraphicsDevice, BodyFrameUpdate); m_viewportSize = m_kinect.ViewportSize; m_videoAllocator = new BufferAllocator<byte>(64 * MagicNumbers.HeadCaptureBytes, 128, 1); base.Initialize(); // oh dear m_holofunkBass.SetBaseForm(m_primaryForm, MagicNumbers.MaxStreamCount); Window.Title = "Holofunk Alpha"; Window.AllowUserResizing = true; /* object nativeWindow = Window.NativeWindow; System.Windows.Forms.Form asForm = nativeWindow as System.Windows.Forms.Form; asForm.SetDesktopBounds(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); //asForm.SetDesktopBounds(100, 100, (int)(m_viewportSize.X * 2), (int)(m_viewportSize.Y * 2)); */ }
/// <summary>Dispose this and all its state.</summary> /// <remarks>This seems to be called twice... so making it robust to that.</remarks> protected override void Dispose(bool disposeManagedResources) { if (m_kinect != null) { m_kinect.Dispose(); m_kinect = null; } if (m_holofunkBass != null) { m_holofunkBass.Dispose(); m_holofunkBass = null; } base.Dispose(disposeManagedResources); }