WPF 3D - Установите ModelVisual3D в поле зрения камеры?
У меня есть кубоид, размеры которого импортируются из XML, поэтому мне нужно быть уверенным, что независимо от размера модели камера всегда может видеть все это. Это для предварительного просмотра. Скорее всего, для наглядности я выделю заголовок, показывающий масштаб.
Я думаю, что мне нужна какая-то функция, которая скажет мне, соответствует ли ModelVisual3D границам FieldOfView
камеры или, возможно, самого ViewPort3D.
Пока у меня есть статический обратный вызов (свойства измерения DependencyProperty
s) при изменении свойств размеров определите, как показано ниже. На данный момент это довольно грубо, но вы поняли, на что я смотрю. Закомментированный раздел показывает примерно, какую логику я ищу
private static void OnCubeDimensionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!valueSemaphore)
{
//while(mainModel.WillClip(mainCamera))
//{
// mainCamera.FieldOfView--;
//}
valueSemaphore = true;
double propertyValue = 0.0;
Product3D p = d as Product3D;
switch (e.Property.Name)
{
case "CubeHeight":
propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 8;
p.CubeHeight = propertyValue;
break;
case "CubeWidth":
propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 5.3;
p.CubeWidth = propertyValue;
break;
case "CubeDepth":
propertyValue = (double.Parse(e.NewValue.ToString()) / 100) * 2.6;
p.CubeDepth = propertyValue;
break;
}
valueSemaphore = false;
}
}
Если кто-нибудь знает, что должно быть в закомментированном разделе, я буду вечно благодарен.
Заранее спасибо.
1 ответ
То, что вам нужно, - это степень 2D-проекции куба на плоскость вида. Затем вы можете просто проверить минимальное и максимальное значения X & Y, чтобы увидеть, виден ли весь куб.
Добавление допускового коэффициента в степень позволит устранить любые ошибки округления.
Я скопировал то, что выглядит как соответствующий раздел кода, отсюда. Затем вы можете установить размер области просмотра соответственно.
public static Rect Get2DBoundingBox(ModelVisual3D mv3d)
{
bool bOK;
Matrix3D m = MathUtils.TryWorldToViewportTransform(vpv, out bOK);
bool bFirst = true;
Rect r = new Rect();
if (mv3d.Content is GeometryModel3D)
{
GeometryModel3D gm3d = (GeometryModel3D) mv3d.Content;
if (gm3d.Geometry is MeshGeometry3D)
{
MeshGeometry3D mg3d = (MeshGeometry3D)gm3d.Geometry;
foreach (Point3D p3d in mg3d.Positions)
{
Point3D pb = m.Transform(p3d);
Point p2d = new Point(pb.X, pb.Y);
if (bFirst)
{
r = new Rect(p2d, new Size(1, 1));
bFirst = false;
}
else
{
r.Union(p2d);
}
}
}
}