This repository has been archived by the owner on May 5, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 493
/
Progam.cs
179 lines (154 loc) · 5.43 KB
/
Progam.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
using System;
using System.Collections.Generic;
using Windows.ApplicationModel.Core;
using Urho;
using Urho.Gui;
using Urho.SharpReality;
using Urho.Physics;
using Urho.Resources;
namespace Physics
{
internal class Program
{
[MTAThread]
static void Main() => CoreApplication.Run(
new UrhoAppViewSource<Progam>(new ApplicationOptions("Data")));
}
public class Progam : StereoApplication
{
Node environmentNode;
Material spatialMaterial;
Material bucketMaterial;
bool surfaceIsValid;
bool positionIsSelected;
Node bucketNode;
Node textNode;
const int MaxBalls = 10;
readonly Queue<Node> balls = new Queue<Node>();
readonly Color validPositionColor = Color.Gray;
readonly Color invalidPositionColor = Color.Red;
public Progam(ApplicationOptions assets) : base(assets) { }
protected override async void Start()
{
base.Start();
environmentNode = Scene.CreateChild();
// Allow tap gesture
EnableGestureTapped = true;
// Create a bucket
bucketNode = Scene.CreateChild();
bucketNode.SetScale(0.1f);
// Create instructions
textNode = bucketNode.CreateChild();
var text3D = textNode.CreateComponent<Text3D>();
text3D.HorizontalAlignment = HorizontalAlignment.Center;
text3D.VerticalAlignment = VerticalAlignment.Top;
text3D.ViewMask = 0x80000000; //hide from raycasts
text3D.Text = "Place on a horizontal\n surface and click";
text3D.SetFont(CoreAssets.Fonts.AnonymousPro, 26);
text3D.SetColor(Color.White);
textNode.Translate(new Vector3(0, 3f, -0.5f));
// Model and Physics for the bucket
var bucketModel = bucketNode.CreateComponent<StaticModel>();
bucketMaterial = Material.FromColor(validPositionColor);
bucketModel.Model = ResourceCache.GetModel("Models/bucket.mdl");
bucketModel.SetMaterial(bucketMaterial);
bucketModel.ViewMask = 0x80000000; //hide from raycasts
bucketNode.CreateComponent<RigidBody>();
var shape = bucketNode.CreateComponent<CollisionShape>();
shape.SetTriangleMesh(bucketModel.Model, 0, Vector3.One, Vector3.Zero, Quaternion.Identity);
// Material for spatial surfaces
spatialMaterial = new Material();
spatialMaterial.SetTechnique(0, CoreAssets.Techniques.NoTextureUnlitVCol, 1, 1);
// make sure 'spatialMapping' capabilaty is enabled in the app manifest.
var spatialMappingAllowed = await StartSpatialMapping(new Vector3(50, 50, 10), 1200);
}
protected override void OnUpdate(float timeStep)
{
if (positionIsSelected)
return;
textNode.LookAt(LeftCamera.Node.WorldPosition, new Vector3(0, 1, 0), TransformSpace.World);
textNode.Rotate(new Quaternion(0, 180, 0), TransformSpace.World);
Ray cameraRay = RightCamera.GetScreenRay(0.5f, 0.5f);
var result = Scene.GetComponent<Octree>().RaycastSingle(cameraRay, RayQueryLevel.Triangle, 100, DrawableFlags.Geometry, 0x70000000);
if (result != null)
{
var angle = Vector3.CalculateAngle(new Vector3(0, 1, 0), result.Value.Normal);
surfaceIsValid = angle < 0.3f; //allow only horizontal surfaces
bucketMaterial.SetShaderParameter("MatDiffColor", surfaceIsValid ? validPositionColor : invalidPositionColor);
bucketNode.Position = result.Value.Position;
}
else
{
// no spatial surfaces found
surfaceIsValid = false;
bucketMaterial.SetShaderParameter("MatDiffColor", validPositionColor);
}
}
public override void OnGestureTapped()
{
if (positionIsSelected)
ThrowBall();
if (surfaceIsValid && !positionIsSelected)
{
positionIsSelected = true;
textNode.Remove();
textNode = null;
}
base.OnGestureTapped();
}
void ThrowBall()
{
// Create a ball (will be cloned)
var ballNode = Scene.CreateChild();
ballNode.Position = RightCamera.Node.Position;
ballNode.Rotation = RightCamera.Node.Rotation;
ballNode.SetScale(0.15f);
var ball = ballNode.CreateComponent<StaticModel>();
ball.Model = CoreAssets.Models.Sphere;
ball.SetMaterial(Material.FromColor(Randoms.NextColor()));
ball.ViewMask = 0x80000000; //hide from raycasts
var ballRigidBody = ballNode.CreateComponent<RigidBody>();
ballRigidBody.Mass = 1f;
ballRigidBody.RollingFriction = 0.5f;
var ballShape = ballNode.CreateComponent<CollisionShape>();
ballShape.SetSphere(1, Vector3.Zero, Quaternion.Identity);
ball.GetComponent<RigidBody>().SetLinearVelocity(RightCamera.Node.Rotation * new Vector3(0f, 0.25f, 1f) * 9 /*velocity*/);
balls.Enqueue(ballNode);
if (balls.Count > MaxBalls)
balls.Dequeue().Remove();
}
public override void OnSurfaceAddedOrUpdated(SpatialMeshInfo surface, Model generatedModel)
{
bool isNew = false;
StaticModel staticModel = null;
Node node = environmentNode.GetChild(surface.SurfaceId, false);
if (node != null)
{
isNew = false;
staticModel = node.GetComponent<StaticModel>();
}
else
{
isNew = true;
node = environmentNode.CreateChild(surface.SurfaceId);
staticModel = node.CreateComponent<StaticModel>();
}
node.Position = surface.BoundsCenter;
node.Rotation = surface.BoundsRotation;
staticModel.Model = generatedModel;
if (isNew)
{
staticModel.SetMaterial(spatialMaterial);
var rigidBody = node.CreateComponent<RigidBody>();
rigidBody.RollingFriction = 0.5f;
rigidBody.Friction = 0.5f;
var collisionShape = node.CreateComponent<CollisionShape>();
collisionShape.SetTriangleMesh(generatedModel, 0, Vector3.One, Vector3.Zero, Quaternion.Identity);
}
else
{
//Update Collision shape
}
}
}
}