/// <summary> /// Export an a perspective or orthographic sensor /// </summary> /// <param name="parent">The parent node in the output XML document</param> /// <param name="obj">The RhinoViewport instance to be exported</param> /// <returns>true if any content was exported</returns> private bool ExportSensor(XmlElement parent, RhinoViewport view) { bool perspective = view.IsPerspectiveProjection; bool orthographic = view.IsParallelProjection; if (!perspective && !orthographic) { Log("Warning: camera type not supported -- ignoring."); return(false); } double left, right, bottom, top, near, far; view.GetFrustum(out left, out right, out bottom, out top, out near, out far); XmlElement sensorElement = m_xmlDocument.CreateElement("sensor"); sensorElement.SetAttribute("type", perspective ? "perspective" : "orthographic"); Transform toWorld = view.GetTransform(CoordinateSystem.Camera, CoordinateSystem.World); toWorld = toWorld * Transform.Mirror(new Plane(new Point3d(0, 0, 0), new Vector3d(0, 0, -1))); toWorld = toWorld * Transform.Mirror(new Plane(new Point3d(0, 0, 0), new Vector3d(-1, 0, 0))); XmlElement toWorldElement = MakeProperty("toWorld", toWorld); if (perspective) { double focusDistance = view.CameraLocation.DistanceTo(view.CameraTarget); double halfDiag, halfVert, halfHoriz; view.GetCameraAngle(out halfDiag, out halfVert, out halfHoriz); toWorld = toWorld * Transform.Mirror(new Plane(new Point3d(0, 0, 0), new Vector3d(0, 0, -1))); sensorElement.AppendChild(MakeProperty("fovAxis", "diagonal")); sensorElement.AppendChild(MakeProperty("fov", 2 * halfDiag * 180 / Math.PI)); sensorElement.AppendChild(MakeProperty("focusDistance", focusDistance)); } else { XmlElement scaleNode = m_xmlDocument.CreateElement("scale"); double scale = (right - left) / 2; scaleNode.SetAttribute("x", ToStringHelper(scale)); scaleNode.SetAttribute("y", ToStringHelper(scale)); toWorldElement.PrependChild(scaleNode); } // Some extra room for nativating using the interactive viewer near /= 10; far *= 10; sensorElement.AppendChild(toWorldElement); sensorElement.AppendChild(MakeProperty("nearClip", near)); sensorElement.AppendChild(MakeProperty("farClip", far)); XmlElement filmElement = m_xmlDocument.CreateElement("film"); filmElement.SetAttribute("type", "hdrfilm"); filmElement.AppendChild(MakeProperty("width", m_settings.xres)); filmElement.AppendChild(MakeProperty("height", m_settings.yres)); sensorElement.AppendChild(filmElement); XmlElement samplerElement = m_xmlDocument.CreateElement("sampler"); samplerElement.SetAttribute("type", "independent"); samplerElement.AppendChild(MakeProperty("sampleCount", m_settings.samplesPerPixel)); sensorElement.AppendChild(samplerElement); parent.AppendChild(sensorElement); return(true); }
//モデル座標から図面の座標へ変換 public Point3d CoordinateTransformation(Point3d world_position) { double halfDiagonalAngle, halfVerticalAngle, halfHorizontalAngle, nearDistance; camera.GetCameraAngle(out halfDiagonalAngle, out halfVerticalAngle, out halfHorizontalAngle); /////////////////////// //view transformation// /////////////////////// //カメラのZ軸と図面のZ軸を揃える Vector3d vec_norm = NormalVector(camera.CameraZ, Vector3d.ZAxis); //回転の軸 double angle = VectorAngle(-Vector3d.ZAxis, camera.CameraZ); //角度 double[,] m1 = new double[4, 4]; m1[0, 0] = vec_norm.X * vec_norm.X * (1 - Math.Cos(angle)) + Math.Cos(angle); m1[1, 0] = vec_norm.X * vec_norm.Y * (1 - Math.Cos(angle)) + vec_norm.Z * Math.Sin(angle); m1[2, 0] = vec_norm.Z * vec_norm.X * (1 - Math.Cos(angle)) - vec_norm.Y * Math.Sin(angle); m1[0, 1] = vec_norm.X * vec_norm.Y * (1 - Math.Cos(angle)) - vec_norm.Z * Math.Sin(angle); m1[1, 1] = vec_norm.Y * vec_norm.Y * (1 - Math.Cos(angle)) + Math.Cos(angle); m1[2, 1] = vec_norm.Y * vec_norm.Z * (1 - Math.Cos(angle)) + vec_norm.X * Math.Sin(angle); m1[0, 2] = vec_norm.Z * vec_norm.X * (1 - Math.Cos(angle)) + vec_norm.Y * Math.Sin(angle); m1[1, 2] = vec_norm.Y * vec_norm.Z * (1 - Math.Cos(angle)) - vec_norm.X * Math.Sin(angle); m1[2, 2] = vec_norm.Z * vec_norm.Z * (1 - Math.Cos(angle)) + Math.Cos(angle); m1[3, 3] = 1; //カメラの上方向と図面のY軸を揃える double angle2 = VectorAngle(camera.CameraX, Vector3d.XAxis); double[,] m2 = new double[4, 4]; m2[0, 0] = Math.Cos(angle2); m2[1, 0] = Math.Sin(angle2); m2[0, 1] = -Math.Sin(angle2); m2[1, 1] = Math.Cos(angle2); m2[2, 2] = 1; m2[3, 3] = 1; //カメラの位置を原点に揃える double[,] pos_cameralocation = MultiplyMatrices(MultiplyMatrices(PointToMatrix(camera.CameraLocation), m1), m2);//m1,m2による変換後のカメラの位置を求める Vector3d vec_location = new Vector3d(pos_cameralocation[0, 0], pos_cameralocation[0, 1], pos_cameralocation[0, 2]); double[,] m3 = new double[4, 4]; m3[0, 0] = 1; m3[1, 1] = 1; m3[2, 2] = 1; m3[3, 0] = -vec_location.X; m3[3, 1] = -vec_location.Y; m3[3, 2] = -vec_location.Z; m3[3, 3] = 1; double[,] screen1 = MultiplyMatrices(PointToMatrix(world_position), m1); double[,] screen2 = MultiplyMatrices(screen1, m2); double[,] screen3 = MultiplyMatrices(screen2, m3); ////////////////////////////// //purojection transformation// ////////////////////////////// Plane planenear, planefar; camera.GetFrustumNearPlane(out planenear); camera.GetFrustumFarPlane(out planefar); double dis_near = camera.CameraLocation.DistanceTo(planenear.Origin); //カメラとNearPlaneの距離を求める double dis_far = camera.CameraLocation.DistanceTo(planefar.Origin); //カメラとFarPlaneの距離を求める //x座標,y座標の値によって正負を返す double direction_y = 1; double direction_x = 1; if (screen3[0, 1] < 0) { direction_y = -1; } if (screen3[0, 0] < 0) { direction_x = -1; } double angle_y = VectorAngle(Vector3d.ZAxis, new Vector3d(0, screen3[0, 1], screen3[0, 2])); double angle_x = VectorAngle(Vector3d.ZAxis, new Vector3d(screen3[0, 0], 0, screen3[0, 2])); double sy = 1 - direction_y * ((screen3[0, 2] - dis_near) * Math.Tan(angle_y)) / screen3[0, 1]; double sx = 1 - direction_x * ((screen3[0, 2] - dis_near) * Math.Tan(angle_x)) / screen3[0, 0]; double[,] m4 = new double[4, 4]; m4[0, 0] = sx; m4[1, 1] = sy; m4[2, 2] = 0; m4[3, 3] = 1; double[,] screen4 = MultiplyMatrices(screen3, m4); ///////////////////////// //screen transformation// ///////////////////////// //変換した座標をビューポートのサイズに合わせる double[,] m5 = new double[4, 4]; List <Point3d> nearrec = new List <Point3d>(); nearrec.AddRange(camera.GetNearRect()); //NearPlaneとビューポートの大きさの比率を求める double sx5 = camera.Size.Width / nearrec[0].DistanceTo(nearrec[1]); double sy5 = camera.Size.Height / nearrec[0].DistanceTo(nearrec[2]); m5[0, 0] = sx5; m5[1, 1] = sy5; m5[3, 3] = 1; double[,] screen5 = MultiplyMatrices(screen4, m5); Point3d pos_screen = new Point3d(screen5[0, 0], screen5[0, 1], screen5[0, 2]); return(pos_screen); }