Creating a Vewport3D camera in XAML is not working - c#

I was trying to create a new Perspective Camera using C# and apply that to my XAML code, but for some reason, when I do it directly in XAML it works fine, but when I do it in C#, it does not work.
Here is the code I got from Microsoft's demonstration: (https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/how-to-create-a-3-d-scene?view=netframeworkdesktop-4.8)
<Viewport3D
Name="SceneViewViewport"
Width="954"
Height="659">
<!-- Defines the camera used to view the 3D object. -->
<Viewport3D.Camera>
<PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" />
</Viewport3D.Camera>
<!-- The ModelVisual3D children contain the 3D models -->
<Viewport3D.Children>
<!-- This ModelVisual3D defines the light cast in the scene. Without light, the 3D
object cannot be seen. Also, the direction of the lights affect shadowing. If desired,
you can create multiple lights with different colors that shine from different directions. -->
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFF" Direction="-0.612372,-0.5,-0.612372" />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D>
<!-- The geometry specifies the shape of the 3D plane. In this sample, a flat sheet is created. -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
TriangleIndices="0,1,2 3,4,5 "
Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 "
TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 "
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " />
</GeometryModel3D.Geometry>
<!-- The material specifies the material applied to the 3D object. In this sample a linear gradient
covers the surface of the 3D object.-->
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<!-- Apply a transform to the object. In this sample, a rotation transform is applied, rendering the
3D object rotated. -->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
Works fine.
Now I put the same code (C#) version, also from Microsoft's demo, and it does not work.
viewport = (Viewport3D)FindName("SceneViewViewport");
SceneViewWidth = (float)viewport.Width;
SceneViewHeight = (float)viewport.Height;
Setup();
void Setup()
{
// Declare scene objects.
Viewport3D myViewport3D = viewport;
Model3DGroup myModel3DGroup = new Model3DGroup();
GeometryModel3D myGeometryModel = new GeometryModel3D();
ModelVisual3D myModelVisual3D = new ModelVisual3D();
// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();
// Specify where in the 3D scene the camera is.
myPCamera.Position = new Point3D(0, 0, 2);
// Specify the direction that the camera is pointing.
myPCamera.LookDirection = new Vector3D(0, 0, -1);
// Define camera's horizontal field of view in degrees.
myPCamera.FieldOfView = 70;
// Asign the camera to the viewport
viewport.Camera = myPCamera;
// Define the lights cast in the scene. Without light, the 3D object cannot
// be seen. Note: to illuminate an object from additional directions, create
// additional lights.
DirectionalLight myDirectionalLight = new DirectionalLight();
myDirectionalLight.Color = Colors.White;
myDirectionalLight.Direction = new Vector3D(-0.61, -0.5, -0.61);
myModel3DGroup.Children.Add(myDirectionalLight);
// The geometry specifes the shape of the 3D plane. In this sample, a flat sheet
// is created.
MeshGeometry3D myMeshGeometry3D = new MeshGeometry3D();
// Create a collection of normal vectors for the MeshGeometry3D.
Vector3DCollection myNormalCollection = new Vector3DCollection();
myNormalCollection.Add(new Vector3D(0, 0, 1));
myNormalCollection.Add(new Vector3D(0, 0, 1));
myNormalCollection.Add(new Vector3D(0, 0, 1));
myNormalCollection.Add(new Vector3D(0, 0, 1));
myNormalCollection.Add(new Vector3D(0, 0, 1));
myNormalCollection.Add(new Vector3D(0, 0, 1));
myMeshGeometry3D.Normals = myNormalCollection;
// Create a collection of vertex positions for the MeshGeometry3D.
Point3DCollection myPositionCollection = new Point3DCollection();
myPositionCollection.Add(new Point3D(-0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, -0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(-0.5, 0.5, 0.5));
myPositionCollection.Add(new Point3D(-0.5, -0.5, 0.5));
myMeshGeometry3D.Positions = myPositionCollection;
// Create a collection of texture coordinates for the MeshGeometry3D.
PointCollection myTextureCoordinatesCollection = new PointCollection();
myTextureCoordinatesCollection.Add(new Point(0, 0));
myTextureCoordinatesCollection.Add(new Point(1, 0));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myTextureCoordinatesCollection.Add(new Point(1, 1));
myTextureCoordinatesCollection.Add(new Point(0, 1));
myTextureCoordinatesCollection.Add(new Point(0, 0));
myMeshGeometry3D.TextureCoordinates = myTextureCoordinatesCollection;
// Create a collection of triangle indices for the MeshGeometry3D.
Int32Collection myTriangleIndicesCollection = new Int32Collection();
myTriangleIndicesCollection.Add(0);
myTriangleIndicesCollection.Add(1);
myTriangleIndicesCollection.Add(2);
myTriangleIndicesCollection.Add(3);
myTriangleIndicesCollection.Add(4);
myTriangleIndicesCollection.Add(5);
myMeshGeometry3D.TriangleIndices = myTriangleIndicesCollection;
// Apply the mesh to the geometry model.
myGeometryModel.Geometry = myMeshGeometry3D;
// The material specifies the material applied to the 3D object. In this sample a
// linear gradient covers the surface of the 3D object.
// Create a horizontal linear gradient with four stops.
LinearGradientBrush myHorizontalGradient = new LinearGradientBrush();
myHorizontalGradient.StartPoint = new Point(0, 0.5);
myHorizontalGradient.EndPoint = new Point(1, 0.5);
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));
myHorizontalGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));
// Define material and apply to the mesh geometries.
DiffuseMaterial myMaterial = new DiffuseMaterial(myHorizontalGradient);
myGeometryModel.Material = myMaterial;
// Apply a transform to the object. In this sample, a rotation transform is applied,
// rendering the 3D object rotated.
RotateTransform3D myRotateTransform3D = new RotateTransform3D();
AxisAngleRotation3D myAxisAngleRotation3d = new AxisAngleRotation3D();
myAxisAngleRotation3d.Axis = new Vector3D(0, 3, 0);
myAxisAngleRotation3d.Angle = 40;
myRotateTransform3D.Rotation = myAxisAngleRotation3d;
myGeometryModel.Transform = myRotateTransform3D;
// Add the geometry model to the model group.
myModel3DGroup.Children.Add(myGeometryModel);
// Add the group of models to the ModelVisual3d.
myModelVisual3D.Content = myModel3DGroup;
//
myViewport3D.Children.Add(myModelVisual3D);
// Apply the viewport to the page so it will be rendered.
this.Content = myViewport3D;
}
I tried using Microsoft's example, found here: "https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/how-to-create-a-3-d-scene?view=netframeworkdesktop-4.8", but nothing changed. The XAML version works as expected, but the C# version only displays an empty screen.

Related

How to create brick pattern in WPF in code? [duplicate]

This question already has answers here:
Creating Diagonal Pattern in WPF
(3 answers)
Create a hatch pattern in WPF
(2 answers)
Shape with slanted lines as background
(2 answers)
Create stripe brush in WPF
(2 answers)
Closed 3 years ago.
This question is similar to others, but my research has not uncovered the answer I seek. I am trying to fill a rectangle with a brick pattern. I understand there is not a HatchBrush in WPF and if there was perhaps I would do this: HatchBrush brush = new HatchBrush(HatchStyle.DiagonalBrick,System.Drawing.Color.Black); But since there is not I am using a DrawingBrush as follows, which fills the rectangle with a darkblue solid color. Where do I specify the DiagonalBrick?
Rectangle fillRect = new Rectangle();
//Try to fill fillRect with a pattern
Rect aRect = new Rect();
aRect.Width = fillRect.Width;
aRect.Height = fillRect.Height;
GeometryGroup rectangle = new GeometryGroup();
GeometryDrawing geomDrawing = new GeometryDrawing(Brushes.DarkBlue,null, rectangle);
DrawingBrush drawingBrush = new DrawingBrush();
rectangle.Children.Add(new RectangleGeometry(aRect, 0, 0));
geomDrawing.Geometry = rectangle;
drawingBrush.Drawing = geomDrawing;
fillRect.Fill = drawingBrush;
There's actually quite a few different ways to do this, but based on the code you've posted I'll assume you want to create your own geometry, using pixels as your coordinate system, and use that to paint a rectangle. This is one of those cases where WPF's flexibility means you have to be a lot more verbose than you would in previous platforms, but let's work through it...
The brick pattern can be achieved by creating a DrawingBrush containing a GeometryDrawing. The trick is to create two bricks of size <60,40> that are offset:
The problem now is the black background poking through. We can solve that by placing a third brick to the left of the one on the bottom, and then setting the DrawBrush's Viewport and Viewbox to the rectangle <0,0,60,80>, and then setting TileMode to "Tile". The code to do this is as follows:
var brickBrush = new DrawingBrush
{
Viewport = new Rect(0, 0, 60, 80),
ViewportUnits = BrushMappingMode.Absolute,
Viewbox = new Rect(0, 0, 60, 80),
ViewboxUnits = BrushMappingMode.Absolute,
TileMode = TileMode.Tile,
Drawing = new GeometryDrawing
{
Brush = new SolidColorBrush(Color.FromRgb(0xB1, 0x78, 0x33)),
Geometry = new GeometryGroup
{
Children = new GeometryCollection(new Geometry[] {
new RectangleGeometry(new Rect( 0, 0, 60, 40)),
new RectangleGeometry(new Rect( 30, 40, 60, 40)),
new RectangleGeometry(new Rect(-30, 40, 60, 40))
}),
},
Pen = new Pen(new SolidColorBrush(Color.FromRgb(0xE1, 0xD7, 0xBD)), 5)
}
};
theRectangle.Fill = brickBrush;
Which will generate the following pattern:
As your WPF skill improves you'll eventually want to start doing stuff like this in XAML. For the purpose of comparison, here is the code needed to achieve the same fill:
<Window.Resources>
<DrawingBrush x:Key="BrickBrush" Viewport="0,0,60,80" ViewportUnits="Absolute" Viewbox="0,0,60,80" ViewboxUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="#B17833">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,60,40" />
<RectangleGeometry Rect="30,40,60,40" />
<RectangleGeometry Rect="-30,40,60,40" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="5" Brush="#E1D7BD" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Window.Resources>
<Rectangle Fill="{StaticResource BrickBrush}" />
You've also alluded to wanting diagonal bricks, to do that you simply add a rotation transform to the DrawingBrush:
var brickBrush = new DrawingBrush
{
Transform = new RotateTransform(45),
... etc ...

How to draw chess board pattern with Brush on Canvas?

I got Canvas and some Rectangles of different width but same height.
I draw Rectangles on Canvas pragramticaly, width calculated in real time when i draw it.
Some of Rectangles have SolidColorBrush but rest should look like chess board:
I tried to do it like this:
private static Brush CreateBrush()
{
// Create a DrawingBrush
var blackBrush = new DrawingBrush();
// Create a Geometry with white background
// Create a GeometryGroup that will be added to Geometry
var gGroup = new GeometryGroup();
gGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 10, 10)));
gGroup.Children.Add(new RectangleGeometry(new Rect(10, 10, 10, 10)));
// Create a GeomertyDrawing
var checkers =
new GeometryDrawing(new SolidColorBrush(Colors.Black), null, gGroup);
var checkersDrawingGroup = new DrawingGroup();
checkersDrawingGroup.Children.Add(checkers);
blackBrush.Drawing = checkersDrawingGroup;
// Set Viewport and TileMode
blackBrush.Viewport = new Rect(0, 0, 0.5, 0.5 );
blackBrush.TileMode = TileMode.Tile;
return blackBrush;
}
As far as Rectangles got different size, same DrawingBrush looks different on different Rectangles - its not repeats to fill it, but stretch.
As i understand, the problem is in blackBrush.Viewport = new Rect(0, 0, 0.5, 0.5 ); - i should set diffrent Viewports according to each Rectangle width, but its no acceptable for me. I need to use one brush for all rectangles of different size and texture should look like one picture - same scale for X and Y, but it can repeat many time in one Rectangle
Maybe there is another Brush type or other way to solve this issues?
Fill free to ask, if my post was unclear, also sorry for my english.
add picture for what i need:
(It's not about width, its about texture fill)
The problem is in the Viewport settings, you should set its ViewportUnits to Absolute instead of RelativeToBoundingBox (as by default):
//we have to use a fixed size for the squares
blackBrush.Viewport = new Rect(0, 0, 60, 60);
blackBrush.Viewport.ViewportUnits = BrushMappingMode.Absolute;
Here is an example showing the checkboard using pure XAML:
<Grid>
<Grid.Background>
<DrawingBrush TileMode="Tile" Viewport="0,0,60,60"
ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="Black"
Geometry="M5,5 L0,5 0,10 5,10 5,5 10,5 10,0 5,0 Z"/>
</DrawingBrush.Drawing>
</DrawingBrush>
</Grid.Background>
</Grid>
By using a DrawingGroup with King King's answer, you can specify different colors for each side:
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="Black" Geometry="M5,5 L0,5 0,10 5,10 5,5 10,5 10,0 5,0 Z"/>
<GeometryDrawing Brush="Blue" Geometry="M0,0 L0,5 0,10 0,5, 10,5 10,10 5,10 5,0 Z"/>
</DrawingGroup>
</DrawingBrush.Drawing>

VisuaBrush Scaling Incorrectly with Canvas as Visual element

I've been fighting with this problem for a few days now and have had zero luck getting it resolved or finding any support on the web. Basically, I am trying to create a VisualBrush with a canvas as the visual element. I want to be able to draw several lines on this canvas and will eventually be mapping it to a 3D surface (2 parallel triangles forming a rectangle). I've set up the texture coordinates and can confirm everything works by simply using an ImageBrush or something of that nature. The problem I am having is that the canvas refuses to maintain its size and is constantly scaled based on the content that is inside it. So for example, if the canvas is 100x100 and I have a single line inside it from (0, 0) to (50, 50), the canvas would be scaled such that only the 50x50 portion with content inside is mapped to the texture coordinates and onto the 3D surface. I have tried many combinations of Viewport/Viewbox/StretchMode/Alignment/etc and can't find anything that stops this from happening. I am setting the Width and Height properties of the canvas so I can't see why it would perform differently in the VisualBrush versus if I simply added it into a grid or some other layout container.
Here's some code to help illustrate the problem.
// create the canvas for the VisualBrush
Canvas drawCanvas = new Canvas();
drawCanvas.Background = Brushes.Transparent; // transparent canvas background so only content is rendered
drawCanvas.Width = 100;
drawCanvas.Height = 100;
// add a line to the canvas
Line l = new Line();
l.X1 = 0;
l.Y1 = 0;
l.X2 = 50;
l.Y2 = 50;
l.Stroke = Brushes.Red;
l.StrokeThickness = 2;
drawCanvas.Children.Add(l);
// create rectangular surface mesh
MeshGeometry3D TableMesh = new MeshGeometry3D();
CreateRectangleModel(
new Point3D(0, 0, 0),
new Point3D(0, 0, 100),
new Point3D(100, 0, 100),
TableMesh);
// need to include texture coordinates for our table mesh to map canvas to 3D model
TableMesh.TextureCoordinates = new PointCollection {
new Point(0, 0), new Point(0, 1), new Point(1, 1),
new Point(1, 1), new Point(0, 1), new Point(0, 0),
new Point(1, 1), new Point(1, 0), new Point(0, 0),
new Point(0, 0), new Point(1, 0), new Point(1, 1)
};
// finally make our visual brush with the canvas we have created
VisualBrush vb = new VisualBrush();
vb.Visual = drawCanvas;
Material TableMaterial = new DiffuseMaterial(vb);
// add our new model to the scene
GeometryModel3D geometry = new GeometryModel3D(TableMesh, TableMaterial);
Model3DGroup group = new Model3DGroup();
group.Children.Add(geometry);
ModelVisual3D previewTable = new ModelVisual3D();
previewTable.Content = group;
MainViewport.Children.Add(previewTable);
And the one function I referenced is
private void CreateRectangleModel(Point3D pStart, Point3D pCorner1, Point3D pEnd, MeshGeometry3D mesh)
{
// pCorner -> O--O <- pEnd
// | /|
// |/ |
// pStart -> O--O <- pCorner2
// find the remaining point for our rectangle
Point3D pCorner2 = new Point3D(
pStart.X + (pEnd.X - pCorner1.X),
pStart.Y + (pEnd.Y - pCorner1.Y),
pStart.Z + (pEnd.Z - pCorner1.Z));
// add necessary triangles to our group (we create 2 facing up, 2 facing down)
CreateTriangleModel(pStart, pCorner1, pEnd, mesh);
CreateTriangleModel(pEnd, pCorner1, pStart, mesh);
CreateTriangleModel(pEnd, pCorner2, pStart, mesh);
CreateTriangleModel(pStart, pCorner2, pEnd, mesh);
}
I can't get the canvas to maintain its set size of 100x100 unless the children content goes all the way to these extremes. For my purposes, the line coordinates could be anywhere within the canvas and I need to have it maintain its desired shape regardless of the content.
Any advice would be greatly appreciated!
Some things to try:
Create an image file of 100x100 pixels by hand and then put it into an ImageBrush, and use that brush in your DiffuseMaterial. This is to confirm that your texture coords, etc are being set up properly.
Instead of using a Transparent Background colour on your Canvas, try Green (this is to see if the texture is being cropped based on transparent pixels)
If the cropping is being done of your texture (due to transparency)...then try putting a rectangle on the Canvas at the dimensions you want the texture to be...maybe that will change something.
Or try using RenderTargetBitmap to create an image from your Canvas visual...then use that image within an ImageBrush. (you can then confirm that the image is of your expected area of 100x100).
Finally, instead of using a Canvas+VisualBrush to create your texture try creating the Brush by using a DrawingBrush+DrawingGroup+GeometryDrawing

How to draw gridline on WPF Canvas?

I need to build a function drawing gridline on the canvas in WPF:
void DrawGridLine(double startX, double startY, double stepX, double stepY,
double slop, double width, double height)
{
// How to implement draw gridline here?
}
How would I go about this?
You don't really have to "draw" anything with WPF. If you want to draw lines, use the appropriate geometries to draw them.
In your case it could be simple really. You're just drawing a grid so you could just create a DrawingBrush to draw a single grid square and tile it to fill in the rest. To draw your tile, you could think of it as drawing X's. So to have a 20x10 tile (which corresponds to stepX and stepY):
(p.s., the slope slop is redundant since you already have the horizontal and vertical step sizes)
<DrawingBrush x:Key="GridTile" Stretch="None" TileMode="Tile"
Viewport="0,0 20,10" ViewportUnits="Absolute">
<!-- ^^^^^^^^^^^ set the size of the tile-->
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<!-- draw a single X -->
<GeometryGroup>
<!-- top-left to bottom-right -->
<LineGeometry StartPoint="0,0" EndPoint="20,10" />
<!-- bottom-left to top-right -->
<LineGeometry StartPoint="0,10" EndPoint="20,0" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<!-- set color and thickness of lines -->
<Pen Thickness="1" Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
That takes care of drawing the lines. Now to be able to draw them offset in your grid from the edges, you need to have another brush where you draw a rectangle with the desired dimensions, filled with your tiles. So to have a starting position of (30, 45) (corresponding to startX and startY) with the width and height, 130x120:
<DrawingBrush x:Key="OffsetGrid" Stretch="None" AlignmentX="Left" AlignmentY="Top">
<DrawingBrush.Transform>
<!-- set the left and top offsets -->
<TranslateTransform X="30" Y="45" />
</DrawingBrush.Transform>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="{StaticResource GridTile}" >
<GeometryDrawing.Geometry>
<!-- set the width and height filled with the tile from the origin -->
<RectangleGeometry Rect="0,0 130,120" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
Then finally to use it, just set it as the background of your grid (or other panel):
<Grid Background="{StaticResource OffsetGrid}">
<!-- ... -->
</Grid>
Here's how it ends up looking like:
If you want to generate the brush dynamically, here's an equivalent function based on the above XAML:
static Brush CreateGridBrush(Rect bounds, Size tileSize)
{
var gridColor = Brushes.Black;
var gridThickness = 1.0;
var tileRect = new Rect(tileSize);
var gridTile = new DrawingBrush
{
Stretch = Stretch.None,
TileMode = TileMode.Tile,
Viewport = tileRect,
ViewportUnits = BrushMappingMode.Absolute,
Drawing = new GeometryDrawing
{
Pen = new Pen(gridColor, gridThickness),
Geometry = new GeometryGroup
{
Children = new GeometryCollection
{
new LineGeometry(tileRect.TopLeft, tileRect.BottomRight),
new LineGeometry(tileRect.BottomLeft, tileRect.TopRight)
}
}
}
};
var offsetGrid = new DrawingBrush
{
Stretch = Stretch.None,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top,
Transform = new TranslateTransform(bounds.Left, bounds.Top),
Drawing = new GeometryDrawing
{
Geometry = new RectangleGeometry(new Rect(bounds.Size)),
Brush = gridTile
}
};
return offsetGrid;
}

C# directx sprite origin

i have this problem when my Sprite rotation origin is fixed at top left corner of window (same with sprite.Draw and sprite.Draw2D)
Either way if i change rotation center it's still at top left. I need sprite to rotate around its Z axis.
Edit:
I have tried this:
hereMatrix pm = Matrix.Translation(_playerPos.X + 8, _playerPos.Y + 8, 0);
sprite.Transform = Matrix.RotationZ(_angle) * pm;
sprite.Draw(playerTexture, textureSize, new Vector3(8, 8, 0), new Vector3(_playerPos.X, _playerPos.Y, 0), Color.White);
But it does not seem to works well...
When you draw it, is it in the correct place?
I believe that the multiplication order is reversed, and that you shouldn't be transforming by the players position in the transform.
// shift centre to (0,0)
sprite.Transform = Matrix.Translation(-textureSize.Width / 2, -textureSize.Height / 2, 0);
// rotate about (0,0)
sprite.Transform *= Matrix.RotationZ(_angle);
sprite.Draw(playerTexture, textureSize, Vector3.Zero,
new Vector3(_playerPos.X, _playerPos.Y, 0), Color.White);
Edit
You could also use the Matrix.Transformation method to get the matrix in one step.
I've got the solution for you, it's a simple method that you can use everytime you want to draw a sprite.
With this method you will be able to rotate the sprite with your desired rotation center.
public void drawSprite(Sprite sprite, Texture texture, Point dimension, Point rotationCenter, float rotationAngle, Point position)
{
sprite.Begin(SpriteFlags.AlphaBlend);
//First draw the sprite in position 0,0 and set your desired rotationCenter (dimension.X and dimension.Y represent the pixel dimension of the texture)
sprite.Draw(texture, new Rectangle(0, 0, dimension.X, dimension.Y), new Vector3(rotationCenter.X, rotationCenter.Y, 0), new Vector3(0, 0, 0), Color.White);
//Then rotate the sprite and then translate it in your desired position
sprite.Transform = Matrix.RotationZ(rotationAngle) * Matrix.Translation(position.X, position.Y, 0);
sprite.End();
}

Categories

Resources