public void BeginDraw_Ray(Ray3f ray, AnyRayHit rayHit, int nStep) { CreateNewPrimitive(); Vector3f hitPos = rayHit.hitPos; // try snap points SnapResult snap = Snaps.FindHitSnapPoint(ray); if (snap != null) { Frame3f snapF = scene.ToWorldFrame(snap.FrameS); hitPos = snapF.Origin; } Frame3f sceneW = scene.SceneFrame; if (rayHit.hitSO == null) { primStartW = sceneW; primStartW.Origin = hitPos; } else { if (scene.Context.TransformManager.ActiveFrameType == FrameType.WorldFrame) { primStartW = sceneW; primStartW.Origin = hitPos; } else if (rayHit.hitSO is PivotSO) { primStartW = (rayHit.hitSO as PivotSO).GetLocalFrame(CoordSpace.WorldCoords); primStartW.Origin = hitPos; } else if (rayHit.hitSO is PrimitiveSO) { // align with object frame as much as possible, given that we still want // to use hit normal... Frame3f objFrame = (rayHit.hitSO as PrimitiveSO).GetLocalFrame(CoordSpace.WorldCoords); int nBestAxis = MathUtil.MostParallelAxis(objFrame, rayHit.hitNormal); int nPerp = (nBestAxis + 1) % 3; primStartW = new Frame3f(hitPos, rayHit.hitNormal, 1); primStartW.ConstrainedAlignAxis(0, objFrame.GetAxis(nPerp), primStartW.Y); } else { primStartW = new Frame3f(hitPos, rayHit.hitNormal, 1); primStartW.ConstrainedAlignAxis(1, sceneW.Y, primStartW.Y); } } primitive.Frame = primStartW; primStartS = scene.ToSceneFrame(primStartW); }
void update_position(AnyRayHit hit) { int nNormalAxis = 1; int nUpAxis = 2; // as we drag object we will align Y with hit surface normal, but // we also want to constrain rotation so it is stable. Hence, we are // going to use world or local frame of target object to stabilize // rotation around normal. Frame3f hitF = TargetScene.SceneFrame; Vector3 targetAxis = hitF.GetAxis(1); if (hit.hitSO is SceneObject) { hitF = (hit.hitSO as SceneObject).GetLocalFrame(CoordSpace.WorldCoords); } bool bUseLocal = (TargetScene.Context.TransformManager.ActiveFrameType == FrameType.LocalFrame); if (bUseLocal && hit.hitSO is SceneObject) { hitF = (hit.hitSO as SceneObject).GetLocalFrame(CoordSpace.WorldCoords); targetAxis = hitF.GetAxis(1); } // if normal is parallel to target, this would become unstable, so use another axis if (Vector3.Dot(targetAxis, hit.hitNormal) > 0.99f) { targetAxis = hitF.GetAxis(0); } if (lastHitObject == null || hit.hitSO != lastHitObject) { lastHitF = new Frame3f(hit.hitPos, hit.hitNormal, nNormalAxis); lastHitF.ConstrainedAlignAxis(nUpAxis, targetAxis, lastHitF.GetAxis(nNormalAxis)); } else { lastHitF.Origin = hit.hitPos; lastHitF.AlignAxis(nNormalAxis, hit.hitNormal); lastHitF.ConstrainedAlignAxis(nUpAxis, targetAxis, lastHitF.GetAxis(nNormalAxis)); } lastHitObject = hit.hitSO; }
// Use this for initialization public override void Awake() { // if we need to auto-configure Rift vs Vive vs (?) VR, we need // to do this before any other F3 setup, because MainCamera will change // and we are caching that in a lot of places... if (AutoConfigVR) { VRCameraRig = gs.VRPlatform.AutoConfigureVR(); } // restore any settings SceneGraphConfig.RestorePreferences(); // set up some defaults // this will move the ground plane down, but the bunnies will be floating... //SceneGraphConfig.InitialSceneTranslate = -4.0f * Vector3f.AxisY; SceneGraphConfig.DefaultSceneCurveVisualDegrees = 0.5f; SceneGraphConfig.DefaultPivotVisualDegrees = 1.5f; SceneGraphConfig.DefaultAxisGizmoVisualDegrees = 10.0f; SceneGraphConfig.InitialSceneTranslate = -4 * Vector3f.AxisY; SceneOptions options = new SceneOptions(); options.UseSystemMouseCursor = false; options.Use2DCockpit = false; options.EnableTransforms = true; options.EnableCockpit = true; options.CockpitInitializer = new PhotoToolCockpit(); options.MouseCameraControls = new MayaCameraHotkeys(); options.SpatialCameraRig = VRCameraRig; // very verbose options.LogLevel = 2; context = new FContext(); context.Start(options); // if you had other gizmos, you would register them here //context.TransformManager.RegisterGizmoType("snap_drag", new SnapDragGizmoBuilder()); //controller.TransformManager.SetActiveGizmoType("snap_drag"); // if you had other tools, you would register them here. context.ToolManager.RegisterToolType(DrawPrimitivesTool.Identifier, new DrawPrimitivesToolBuilder()); context.ToolManager.RegisterToolType(DrawSurfaceCurveTool.Identifier, new DrawSurfaceCurveToolBuilder() { AttachCurveToSurface = true, DefaultSamplingRateS = 0.0025f, DefaultSurfaceOffsetS = 0.0025f, CurveMaterialF = () => { var mat = context.Scene.DefaultCurveSOMaterial.Clone(); mat.RGBColor = Colorf.VideoRed; return(mat); } }); context.ToolManager.SetActiveToolType(DrawSurfaceCurveTool.Identifier, ToolSide.Right); // Set up standard scene lighting if requested if (options.EnableDefaultLighting) { GameObject lighting = GameObject.Find("SceneLighting"); if (lighting == null) { lighting = new GameObject("SceneLighting"); } SceneLightingSetup setup = lighting.AddComponent <SceneLightingSetup>(); setup.Context = context; setup.LightDistance = 30.0f; // related to total scene scale... } Context.Scene.DisableSelectionMaterial = true; /* * Import elements of Unity scene that already exist into the FScene */ // set up ground plane geometry (optional) GameObject groundPlane = GameObject.Find("GroundPlane"); if (groundPlane != null && groundPlane.IsVisible()) { context.Scene.AddWorldBoundsObject(groundPlane); } float fSquareSize = 1.0f; Vector3f eyePos = context.ActiveCamera.GetPosition(); System.Random rand = new System.Random(31337); // [RMS] this path only works in Editor, is relative to top-level project directory string sPhotoFolder = "Data\\PhotoSets\\kitchen"; string[] photos = Directory.GetFiles(sPhotoFolder); foreach (string filename in photos) { Texture2D tex = load_texture(filename); if (tex == null) { continue; } float fScale = fSquareSize / (float)tex.width; if (tex.height > tex.width) { fScale = fSquareSize / (float)tex.height; } float w = fScale * (float)tex.width; float h = fScale * (float)tex.height; TrivialRectGenerator rectgen = new TrivialRectGenerator() { Width = w, Height = h }; rectgen.Generate(); DMesh3 mesh = new DMesh3(MeshComponents.VertexUVs); rectgen.MakeMesh(mesh); SOMaterial material = new SOMaterial() { Name = "photomaterial", Type = SOMaterial.MaterialType.TextureMap, RGBColor = Colorf.White }; material.MainTexture = tex; DMeshSO so = new DMeshSO(); so.Create(mesh, material); context.Scene.AddSceneObject(so); float horz = rand.Next(-50, 50); float vert = rand.Next(-20, 25); int mult = 1000; float dist = (float)(rand.Next(2 * mult, 3 * mult)) / (float)mult; Ray3f r = VRUtil.MakeRayFromSphereCenter(horz, vert); r.Origin += eyePos; float fRayT = 0.0f; RayIntersection.Sphere(r.Origin, r.Direction, eyePos, dist, out fRayT); Vector3f v = r.Origin + fRayT * r.Direction; Frame3f f = new Frame3f(v, v.Normalized); Vector3f toEye = context.ActiveCamera.GetPosition() - f.Origin; toEye.Normalize(); f.AlignAxis(1, toEye); f.ConstrainedAlignAxis(2, Vector3f.AxisY, f.Y); so.SetLocalFrame(f, CoordSpace.WorldCoords); } }
public void UpdateTracking(Cockpit cockpit, fCamera camera) { fGameObject cockpitGO = cockpit.RootGameObject; if (!bInitialized) { currentFrame = cockpit.GetLevelViewFrame(CoordSpace.WorldCoords); currentFrame.ConstrainedAlignAxis(2, Vector3f.AxisZ, Vector3f.AxisY); bInitialized = true; } Vector3f vCamFW = camera.Forward(); vCamFW[1] = 0; vCamFW.Normalize(); // I don't think this is strictly necessary but // better to be safe for now... Vector3f vCamPos = camera.GetPosition(); //if (tracking_debug == null) // tracking_debug = UnityUtil.CreatePrimitiveGO("tracking_indicator", PrimitiveType.Sphere, MaterialUtil.CreateStandardMaterial(Color.green), false); //tracking_debug.transform.position = vCamPos + 15.0f * vCamFW; //if (tracking_avg == null) { // tracking_avg = UnityUtil.CreatePrimitiveGO("tracking_indicator", PrimitiveType.Sphere, MaterialUtil.CreateStandardMaterial(Color.blue), false); // tracking_avg.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); //} //tracking_avg.transform.position = vCamPos + 10.0f * vSlowViewDirTrack; //tracking_debug.SetVisible(false); //tracking_avg.SetVisible(false); if (vSlowViewDirTrack == Vector3f.Zero) { vSlowViewDirTrack = vCamFW; } float slowTrackSpeed = 0.05f; vSlowViewDirTrack = VRUtil.AngleLerp(vSlowViewDirTrack, vCamFW, slowTrackSpeed); // head position tracking if (IsLocked == false) { cockpitGO.SetPosition(vCamPos); } //Vector3 vDelta = (camera.transform.position - RootGameObject.transform.position); //if (vDelta.magnitude > 0.2f) // RootGameObject.transform.position = camera.transform.position; ////else if ( vDelta.magnitude > 0.05f) //else // RootGameObject.transform.position = // (1.0f - TrackingSpeed) * RootGameObject.transform.position + // (TrackingSpeed) * camera.transform.position; float RotationSpeed = 200.0f; float WarmupTrackingAngleThresh = 55.0f; float ImmediateTrackingAngleThresh = 65.0f; float StopTrackingAngleThresh = 5.0f; float TrackingWarmupDelay = 2.0f; float TrackingCooldownDelay = 0.75f; //Vector3 vCockpitFW = cockpitGO.transform.forward; Vector3f vCockpitFW = currentFrame.Z; float fSlowHDeviation = VRUtil.PlaneAngle(vCockpitFW, vSlowViewDirTrack); float fActualViewDeviation = VRUtil.PlaneAngle(vCockpitFW, vCamFW); bool bDoTrack = false; if (eState == TrackingState.NotTracking) { //tracking_debug.GetComponent<Renderer>().material = MaterialUtil.CreateStandardMaterial(Color.green); if (fSlowHDeviation > WarmupTrackingAngleThresh) { set_tracking_state(TrackingState.TrackingWarmup); stateChangeStartTime = FPlatform.RealTime(); } } else if (eState == TrackingState.TrackingWarmup) { //tracking_debug.GetComponent<Renderer>().material = MaterialUtil.CreateStandardMaterial(Color.yellow); if (fSlowHDeviation > ImmediateTrackingAngleThresh) { set_tracking_state(TrackingState.Tracking); } else if (fSlowHDeviation > WarmupTrackingAngleThresh) { if ((FPlatform.RealTime() - stateChangeStartTime) > TrackingWarmupDelay) { set_tracking_state(TrackingState.Tracking); } } else { set_tracking_state(TrackingState.NotTracking); } } else if (eState == TrackingState.Tracking) { bDoTrack = true; //tracking_debug.GetComponent<Renderer>().material = MaterialUtil.CreateStandardMaterial(Color.red); if (fActualViewDeviation < StopTrackingAngleThresh) { set_tracking_state(TrackingState.TrackingCooldown); stateChangeStartTime = FPlatform.RealTime(); } } else if (eState == TrackingState.TrackingCooldown) { bDoTrack = true; //tracking_debug.GetComponent<Renderer>().material = MaterialUtil.CreateStandardMaterial(Color.gray); if (fActualViewDeviation < StopTrackingAngleThresh) { if ((FPlatform.RealTime() - stateChangeStartTime) > TrackingCooldownDelay) { set_tracking_state(TrackingState.NotTracking); bDoTrack = false; } } else { set_tracking_state(TrackingState.Tracking); } } if (IsLocked) { bDoTrack = false; set_tracking_state(TrackingState.NotTracking); } if (bDoTrack) { float dt = (float)(FPlatform.RealTime() - animation_last_time); float fDelta = RotationSpeed * dt; Vector3f vCurrent = new Vector3f(vCockpitFW[0], 0, vCockpitFW[2]).Normalized; Vector3f vTarget = new Vector3f(vSlowViewDirTrack[0], 0, vSlowViewDirTrack[2]).Normalized; //Vector3 vTarget = new Vector3(vCamFW[0], 0, vCamFW[2]).normalized; Vector3f c = Vector3f.Cross(vCurrent, vTarget); float a = Vector3f.AngleD(vCurrent, vTarget); float fSign = (c[1] < 0) ? -1.0f : 1.0f; float fRotAngle = Math.Min(a, fDelta) * fSign; currentFrame.Rotate(Quaternionf.AxisAngleD(Vector3f.AxisY, fRotAngle)); } cockpitGO.SetRotation(currentFrame.Rotation); animation_last_time = FPlatform.RealTime(); if (indicator == null) { indicator = new CockpitTrackingWidget(); indicator.Create(this, cockpit); cockpit.AddUIElement(indicator, false); } indicator.EnableIndicator = show_indicator; }
public static void quick_test() { DMesh3 mesh = StandardMeshReader.ReadMesh("c:\\scratch\\block.obj"); DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true); Vector3d rayCenter = new Vector3d(0, 0, 1); Frame3f rayFrame = new Frame3f(rayCenter, Vector3d.AxisZ); List <Frame3f> frames = new List <Frame3f>(); // how far into surface we will inset float SurfaceOffset = 0.01f; double step = 2.5f; for (double angle = 0; angle < 360; angle += step) { double dx = Math.Cos(angle * MathUtil.Deg2Rad), dy = Math.Sin(angle * MathUtil.Deg2Rad); Vector3d dir = dx * (Vector3d)rayFrame.X + dy * (Vector3d)rayFrame.Y; Ray3d ray = new Ray3d(rayFrame.Origin, dir.Normalized); Frame3f hitFrame; if (MeshQueries.RayHitPointFrame(mesh, spatial, ray, out hitFrame)) { frames.Add(hitFrame); } } int N = frames.Count; for (int k = 0; k < N; ++k) { Frame3f f = frames[k]; int prev = (k == 0) ? N - 1 : k - 1; int next = (k + 1) % N; //Vector3f dv = frames[(k + 1) % frames.Count].Origin - f.Origin; Vector3f dv = frames[next].Origin - frames[prev].Origin; dv.Normalize(); f.ConstrainedAlignAxis(0, dv, f.Z); f.Origin = f.Origin + SurfaceOffset * f.Z; frames[k] = f; } //Frame3f f = frames[0]; //Vector3f dv = (frames[1].Origin - frames[0].Origin).Normalized; //f.ConstrainedAlignAxis(1, dv, f.Z); //for (int k = 1; k < frames.Count; ++k) { // f.Origin = frames[k].Origin; // f.AlignAxis(2, frames[k].Z); // frames[k] = f; //} List <Vector3d> vertices = frames.ConvertAll((ff) => { return((Vector3d)ff.Origin); }); TubeGenerator tubegen = new TubeGenerator() { Vertices = vertices, Polygon = Polygon2d.MakeCircle(0.05, 16), NoSharedVertices = false }; DMesh3 tubeMesh = tubegen.Generate().MakeDMesh(); TestUtil.WriteTestOutputMeshes(new List <IMesh>() { mesh, tubeMesh }, "curve_tube.obj"); SimpleQuadMesh stripMeshY = new SimpleQuadMesh(); double w = 0.1; int preva = -1, prevb = -1; for (int k = 0; k < N; ++k) { Vector3d pa = frames[k].Origin + w * (Vector3d)frames[k].Y; Vector3d pb = frames[k].Origin - w * (Vector3d)frames[k].Y; int a = stripMeshY.AppendVertex(pa); int b = stripMeshY.AppendVertex(pb); if (preva != -1) { stripMeshY.AppendQuad(preva, prevb, b, a); } preva = a; prevb = b; } stripMeshY.AppendQuad(preva, prevb, 1, 0); SimpleQuadMesh.WriteOBJ(stripMeshY, TEST_OUTPUT_PATH + "quadstripy.obj", WriteOptions.Defaults); SimpleQuadMesh stripMeshZ = new SimpleQuadMesh(); preva = -1; prevb = -1; double wz = 0.1; for (int k = 0; k < N; ++k) { Vector3d pa = frames[k].Origin + wz * (Vector3d)frames[k].Z; Vector3d pb = frames[k].Origin - wz * (Vector3d)frames[k].Z; int a = stripMeshZ.AppendVertex(pa); int b = stripMeshZ.AppendVertex(pb); if (preva != -1) { stripMeshZ.AppendQuad(preva, prevb, b, a); } preva = a; prevb = b; } stripMeshZ.AppendQuad(preva, prevb, 1, 0); SimpleQuadMesh.WriteOBJ(stripMeshZ, TEST_OUTPUT_PATH + "quadstripz.obj", WriteOptions.Defaults); }