/// <summary> /// From min and max coords of the BB, project them according to the active view, for determining zooming scale /// </summary> /// <param name="min"> The min coord of BB </param> /// <param name="max"> The max coord of BB </param> /// <param name="activeView"> Active view to zoom </param> /// <returns> Returns an array of two vectos in screen space </returns> private Vector2[] findMaxPoints(Vector3 min, Vector3 max, Canguro.View.GraphicView activeView) { Vector3[] boundingVolume = new Vector3[8]; Vector2[] screen = new Vector2[2]; screen[0] = new Vector2(float.MaxValue, float.MaxValue); screen[1] = new Vector2(float.MinValue, float.MinValue); boundingVolume[0] = min; boundingVolume[1] = new Vector3(min.X, min.Y, max.Z); boundingVolume[2] = new Vector3(max.X, min.Y, max.Z); boundingVolume[3] = new Vector3(max.X, min.Y, min.Z); boundingVolume[4] = new Vector3(max.X, max.Y, min.Z); boundingVolume[5] = max; boundingVolume[6] = new Vector3(min.X, max.Y, max.Z); boundingVolume[7] = new Vector3(min.X, max.Y, min.Z); for (int i = 0; i < boundingVolume.GetLength(0); ++i) { activeView.Project(ref boundingVolume[i]); screen[0].X = (screen[0].X > boundingVolume[i].X) ? boundingVolume[i].X : screen[0].X; screen[0].Y = (screen[0].Y > boundingVolume[i].Y) ? boundingVolume[i].Y : screen[0].Y; screen[1].X = (screen[1].X < boundingVolume[i].X) ? boundingVolume[i].X : screen[1].X; screen[1].Y = (screen[1].Y < boundingVolume[i].Y) ? boundingVolume[i].Y : screen[1].Y; } return screen; }
/// <summary> Builds an extrusion from the shape along a curve </summary> /// <param name="shape"> An array indicating the shape points ordered counter_clockwise. First index is for vertex and second for normals. </param> /// <param name="axis"> The curve that must be followed. Array of vertixes. </param> /// <param name="axisDerivative"> The derivative at each vertex in the curve. </param> /// <param name="extrudedMesh"> A ref variable containing the extruded mesh. First index refers to vertices and the second to normals. </param> public static void Build(Vector2[][] shape, Vector3[] axis, Vector3[] axisDerivative, ref Vector3[,] extrudedMesh, ref int[] extrudedIndices, bool faceNormals, short[] cover, Vector3[] origAxes) { // Get the number of segments in the curve nPointSegments = axis.GetLength(0); // Get the number of vertices in the shape nShapeVertices = shape[0].GetLength(0); // Initialize some counters meshVertex = 0; //index = 0; // How many vertices in the mesh are we going to have? int coverSize = cover.Length; nMeshVertices = nShapeVertices * (nPointSegments - 1) * 6 + 2 * coverSize; // 6 vertices per face // Just get memory when necessary (vectors) if (extrudedMesh == null || nMeshVertices != extrudedMesh.GetLength(1)) extrudedMesh = new Vector3[2, nMeshVertices]; // Just get memory when necessary (colors) if (extrudedIndices == null || nMeshVertices != extrudedIndices.GetLength(0)) extrudedIndices = new int[nMeshVertices]; for (segment = 0; segment < nPointSegments - 1; ++segment) { // Compute the plane at the current point in the curve if (axisDerivative != null && axisDerivative[segment] != Vector3.Empty) lineDir = axisDerivative[segment]; // When no derivatives are computed, use instead the line direction else { if (segment == nPointSegments - 1) lineDir = axis[nPointSegments - 1] - axis[nPointSegments - 2]; else lineDir = axis[segment + 1] - axis[segment]; lineDir.Normalize(); } // Check if we have a 'good' value checkIntegrity(ref lineDir); // and compute the local axes at the current curve point currAxes = computeLocalSystem(lineDir, origAxes); currDir = lineDir; if (segment > 0) { temp1 = nextAxes[0]; temp2 = nextAxes[1]; temp3 = nextAxes[2]; } int auxSegment = segment + 1; // Compute the plane at the next point in the curve if (axisDerivative != null && axisDerivative[auxSegment] != Vector3.Empty) lineDir = axisDerivative[auxSegment]; // When no derivatives are computed, use instead the line direction else { if (auxSegment == nPointSegments - 1) lineDir = axis[nPointSegments - 1] - axis[nPointSegments - 2]; else lineDir = axis[auxSegment + 1] - axis[auxSegment]; lineDir.Normalize(); } lineDir += currDir; lineDir.Normalize(); // Check if we have a 'good' value checkIntegrity(ref lineDir); nextAxes = computeLocalSystem(lineDir, origAxes); if (segment > 0) { currAxes[0] = temp1; currAxes[1] = temp2; currAxes[2] = temp3; } // Make start cover if (segment == 0) { for (int i = 0; i < coverSize; ++i) { extrudedMesh[0, meshVertex] = axis[segment] + shape[0][cover[i]].X * currAxes[0] + shape[0][cover[i]].Y * currAxes[1]; extrudedMesh[1, meshVertex] = -currAxes[2]; extrudedIndices[meshVertex] = cover[i]; ++meshVertex; } } // Make end cover else if (auxSegment == nPointSegments - 1) { for (int i = coverSize - 1; i >= 0; --i) { extrudedMesh[0, meshVertex] = axis[auxSegment] + shape[0][cover[i]].X * nextAxes[0] + shape[0][cover[i]].Y * nextAxes[1]; extrudedMesh[1, meshVertex] = nextAxes[2]; extrudedIndices[meshVertex] = nShapeVertices * segment + cover[i]; ++meshVertex; } } // Fill vertex array for (vertex = 0; vertex < nShapeVertices; ++vertex) { // Mesh vertices - First triangle extrudedMesh[0, meshVertex] = axis[segment] + shape[0][vertex].X * currAxes[0] + shape[0][vertex].Y * currAxes[1]; extrudedMesh[1, meshVertex] = shape[1][vertex].X * currAxes[0] + shape[1][vertex].Y * currAxes[1]; extrudedIndices[meshVertex] = nShapeVertices * segment + vertex; ++meshVertex; extrudedMesh[0, meshVertex] = axis[auxSegment] + shape[0][vertex].X * nextAxes[0] + shape[0][vertex].Y * nextAxes[1]; extrudedMesh[1, meshVertex] = shape[1][vertex].X * nextAxes[0] + shape[1][vertex].Y * nextAxes[1]; extrudedIndices[meshVertex] = nShapeVertices * auxSegment + vertex; ++meshVertex; if (vertex + 1 < nShapeVertices) { extrudedMesh[0, meshVertex] = axis[auxSegment] + shape[0][vertex + 1].X * nextAxes[0] + shape[0][vertex + 1].Y * nextAxes[1]; extrudedIndices[meshVertex] = nShapeVertices * auxSegment + vertex + 1; if (faceNormals) extrudedMesh[1, meshVertex] = shape[1][vertex].X * nextAxes[0] + shape[1][vertex].Y * nextAxes[1]; else extrudedMesh[1, meshVertex] = shape[1][vertex+1].X * nextAxes[0] + shape[1][vertex+1].Y * nextAxes[1]; } else { extrudedMesh[0, meshVertex] = axis[auxSegment] + shape[0][0].X * nextAxes[0] + shape[0][0].Y * nextAxes[1]; extrudedIndices[meshVertex] = nShapeVertices * auxSegment; if (faceNormals) extrudedMesh[1, meshVertex] = shape[1][nShapeVertices - 1].X * nextAxes[0] + shape[1][nShapeVertices - 1].Y * nextAxes[1]; else extrudedMesh[1, meshVertex] = shape[1][0].X * nextAxes[0] + shape[1][0].Y * nextAxes[1]; } ++meshVertex; // Mesh vertices - Second triangle extrudedMesh[0, meshVertex] = extrudedMesh[0, meshVertex - 3]; extrudedMesh[1, meshVertex] = extrudedMesh[1, meshVertex - 3]; extrudedIndices[meshVertex] = extrudedIndices[meshVertex - 3]; ++meshVertex; extrudedMesh[0, meshVertex] = extrudedMesh[0, meshVertex - 2]; extrudedMesh[1, meshVertex] = extrudedMesh[1, meshVertex - 2]; extrudedIndices[meshVertex] = extrudedIndices[meshVertex - 2]; ++meshVertex; if (vertex + 1 < nShapeVertices) { extrudedMesh[0, meshVertex] = axis[segment] + shape[0][vertex + 1].X * currAxes[0] + shape[0][vertex + 1].Y * currAxes[1]; extrudedIndices[meshVertex] = nShapeVertices * segment + vertex + 1; if (faceNormals) extrudedMesh[1, meshVertex] = shape[1][vertex].X * currAxes[0] + shape[1][vertex].Y * currAxes[1]; else extrudedMesh[1, meshVertex] = shape[1][vertex + 1].X * currAxes[0] + shape[1][vertex + 1].Y * currAxes[1]; } else { extrudedMesh[0, meshVertex] = axis[segment] + shape[0][0].X * currAxes[0] + shape[0][0].Y * currAxes[1]; extrudedIndices[meshVertex] = nShapeVertices * segment; if (faceNormals) extrudedMesh[1, meshVertex] = shape[1][nShapeVertices - 1].X * currAxes[0] + shape[1][nShapeVertices - 1].Y * currAxes[1]; else extrudedMesh[1, meshVertex] = shape[1][0].X * currAxes[0] + shape[1][0].Y * currAxes[1]; } ++meshVertex; } } }
/// <summary> /// Constructs a 2D texture from a matrix of 3D data vectors. /// </summary> /// <param name="window">A reference to the Direct3D-capable window containing the rendering engine.</param> /// <param name="data">A matrix of 3D data vectors that will make up the texture on the GPU.</param> public Texture(Window3D window, Vector3[,] data) : this(window) { int h = data.GetLength(0); int w = data.GetLength(1); int szVector = SizeOf<Vector4>(); ImageBuffer = Tag(new DataStream(szVector * h * w, true, true)); foreach (Vector3 x in data) { ImageBuffer.Write((Vector4)x); } Image = Tag(new Texture2D ( Device3D, CreateTextureDescription(h, w, Formats.Float4), new DataRectangle(ImageBuffer.DataPointer, w * szVector) )); SRV = Tag(new ShaderResourceView(Device3D, Image)); }
/// <summary> Builds an extrusion from the shape along a curve </summary> /// <param name="shape"> An array indicating the shape points ordered counter_clockwise. First index is for vertex and second for normals. </param> /// <param name="axis"> The curve that must be followed. Array of vertixes. </param> /// <param name="axisDerivative"> The derivative at each vertex in the curve. </param> /// <param name="extrudedMesh"> A ref variable containing the extruded mesh. First index refers to vertices and the second to normals. </param> /// <param name="meshIB"> A ref variable containing the union rules for the extruded mesh (index buffer) </param> /// <param name="origAxes"></param> public static void Build(Vector2[][] shape, short[] shapeIndices, Vector2 cardinalPointOffset, Vector3[] axis, Vector3[] axisDerivative, ref Vector3[,] extrudedMesh, ref short[] meshIB, Vector3[] origAxes) { // Get the number of segments in the curve nPointSegments = axis.GetLength(0); // Get the number of vertices in the shape nShapeVertices = shapeIndices.Length; // Initialize some counters meshVertex = 0; index = 0; currDir = Vector3.Empty; // How many vertices in the mesh are we going to have? nMeshVertices = nShapeVertices * nPointSegments; // Determine the number of indices for mesh tesellation indexBufferSize = ((nShapeVertices - 1) * 2) * (nPointSegments - 1) * 3; // nMeshVertices * 2 = Number of faces per segment // Just get memory when necessary if (extrudedMesh == null || nMeshVertices != extrudedMesh.GetLength(0)) extrudedMesh = new Vector3[2, nMeshVertices]; if (meshIB == null || indexBufferSize != meshIB.GetLength(0)) meshIB = new short[indexBufferSize]; for (segment = 0; segment < nPointSegments; ++segment) { // Compute the plane at the current point in the curve if (axisDerivative != null && axisDerivative[segment] != Vector3.Empty) lineDir = axisDerivative[segment]; // When no derivatives are computed, use instead the line direction else { if (segment == nPointSegments - 1) lineDir = axis[nPointSegments - 1] - axis[nPointSegments - 2]; else lineDir = axis[segment + 1] - axis[segment]; lineDir.Normalize(); } lastDir = lineDir; lineDir += currDir; lineDir.Normalize(); // Check if we have a 'good' value checkIntegrity(ref lineDir); // and compute the local axes at the current curve point currAxes = computeLocalSystem(lineDir, origAxes); currDir = lastDir; // Fill vertex array for (vertex = 0; vertex < nShapeVertices; ++vertex, ++meshVertex) { // Mesh vertices extrudedMesh[0, meshVertex] = axis[segment] + (shape[0][shapeIndices[vertex]].X - cardinalPointOffset.X) * currAxes[0] + (shape[0][shapeIndices[vertex]].Y - cardinalPointOffset.Y) * currAxes[1]; // Mesh normals extrudedMesh[1, meshVertex] = shape[1][shapeIndices[vertex]].X * currAxes[0] + shape[1][shapeIndices[vertex]].Y * currAxes[1]; } } // Index buffer for (segment = 0; segment < nPointSegments - 1; ++segment) { baseIndex = segment * nShapeVertices; for (shapeVertex = 0; shapeVertex < nShapeVertices - 1; ++shapeVertex) { // First triangle meshIB[index++] = (short)(baseIndex + shapeVertex); meshIB[index++] = (short)(baseIndex + shapeVertex + nShapeVertices); meshIB[index++] = (short)(baseIndex + shapeVertex + nShapeVertices + 1); // Second triangle meshIB[index++] = (short)(baseIndex + shapeVertex); meshIB[index++] = (short)(baseIndex + shapeVertex + nShapeVertices + 1); meshIB[index++] = (short)(baseIndex + shapeVertex + 1); } } }