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
|
// Copyright 2014 Intel Corporation All Rights Reserved
//
// Intel makes no representations about the suitability of this software for any purpose.
// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// Intel does not assume any responsibility for any errors which may appear in this software
// nor any responsibility to update it.
#include <algorithm>
#include <cmath>
#include "camera.h"
#include "util.h"
using namespace DirectX;
OrbitCamera::OrbitCamera()
{
// Defaults
mCenter = XMVectorSet(0, 0, 0, 0);
mUp = XMVectorSet(0, 1, 0, 0);
mRadius = 1.0f;
mMinRadius = 1.0f;
mMaxRadius = 1.0f;
mLongAngle = 0.0f;
mLatAngle = 0.0f;
// Set up interaction context (i.e. touch input processing, etc)
ThrowIfFailed(CreateInteractionContext(&mInteractionContext));
ThrowIfFailed(SetPropertyInteractionContext(mInteractionContext, INTERACTION_CONTEXT_PROPERTY_FILTER_POINTERS, TRUE));
{
INTERACTION_CONTEXT_CONFIGURATION config[] =
{
{INTERACTION_ID_MANIPULATION,
INTERACTION_CONFIGURATION_FLAG_MANIPULATION |
INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_X |
INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_Y |
INTERACTION_CONFIGURATION_FLAG_MANIPULATION_SCALING |
INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_INERTIA |
INTERACTION_CONFIGURATION_FLAG_MANIPULATION_SCALING_INERTIA |
INTERACTION_CONFIGURATION_FLAG_MANIPULATION_MULTIPLE_FINGER_PANNING
},
};
ThrowIfFailed(SetInteractionConfigurationInteractionContext(mInteractionContext, ARRAYSIZE(config), config));
}
ThrowIfFailed(RegisterOutputCallbackInteractionContext(mInteractionContext, OrbitCamera::StaticInteractionOutputCallback, this));
}
OrbitCamera::~OrbitCamera()
{
DestroyInteractionContext(mInteractionContext);
}
void OrbitCamera::View(
DirectX::XMVECTOR center, float radius, float minRadius, float maxRadius,
float longAngle, float latAngle)
{
mCenter = center;
mRadius = radius;
mMinRadius = minRadius;
mMaxRadius = maxRadius;
mLongAngle = longAngle;
mLatAngle = latAngle;
UpdateData();
}
void OrbitCamera::Projection(float fov, float aspect)
{
float fovY = (aspect <= 1.0 ? fov : fov / aspect);
mProjection = XMMatrixPerspectiveFovRH(fovY, aspect, 10000.0f, 0.1f);
UpdateData();
}
void OrbitCamera::UpdateData()
{
mEye = XMVectorSet(
mRadius * std::sin(mLatAngle) * std::cos(mLongAngle),
mRadius * std::cos(mLatAngle),
mRadius * std::sin(mLatAngle) * std::sin(mLongAngle),
0.0f);
mView = XMMatrixLookAtRH(mEye, mCenter, mUp);
mViewProjection = XMMatrixMultiply(mView, mProjection);
}
void OrbitCamera::OrbitX(float angle)
{
mLongAngle += angle;
UpdateData();
}
void OrbitCamera::OrbitY(float angle)
{
float limit = XM_PI * 0.01f;
mLatAngle = std::max(limit, std::min(XM_PI-limit, mLatAngle + angle));
UpdateData();
}
void OrbitCamera::ZoomRadius(float delta)
{
mRadius = std::max(mMinRadius, std::min(mMaxRadius, mRadius + delta));
UpdateData();
}
void OrbitCamera::ZoomRadiusScale(float delta)
{
mRadius = std::max(mMinRadius, std::min(mMaxRadius, mRadius * delta));
UpdateData();
}
void OrbitCamera::AddPointer(UINT pointerId)
{
AddPointerInteractionContext(mInteractionContext, pointerId);
}
void OrbitCamera::ProcessPointerFrames(UINT pointerId, const POINTER_INFO* pointerInfo)
{
ProcessPointerFramesInteractionContext(mInteractionContext, 1, 1, pointerInfo);
}
void OrbitCamera::RemovePointer(UINT pointerId)
{
RemovePointerInteractionContext(mInteractionContext, pointerId);
}
void OrbitCamera::ProcessInertia()
{
ProcessInertiaInteractionContext(mInteractionContext);
}
VOID CALLBACK OrbitCamera::StaticInteractionOutputCallback(VOID *clientData, const INTERACTION_CONTEXT_OUTPUT *output)
{
auto camera = reinterpret_cast<OrbitCamera*>(clientData);
camera->InteractionOutputCallback(output);
}
void OrbitCamera::InteractionOutputCallback(const INTERACTION_CONTEXT_OUTPUT *output)
{
switch(output->interactionId)
{
case INTERACTION_ID_MANIPULATION: {
auto delta = &output->arguments.manipulation.delta;
OrbitX(delta->translationX * 0.0007f);
OrbitY(-delta->translationY * 0.0007f);
ZoomRadiusScale(1.0f / delta->scale);
break;
}
default:
break;
}
}
|