I have a set of images in which each image needs to be able to rotate to 90 degrees, 180 degrees, and 270 degrees. All of these images are of type Texture2D. Are there built in functions to accomplish this for me? Or should I load additional rotated images of each image? Or is there a better way of completing this task?
You can rotate (and scale) your Textures as you draw them to the buffer using SpriteBatch.Draw, although you will need to specify most (or all) of the arguments. Angles are given in radians.
SpriteBatch.Begin();
angle = (float)Math.PI / 2.0f; // 90 degrees
scale = 1.0f;
SpriteBatch.Draw(myTexture, sourceRect, destRect, Color.White, angle,
position, scale, SpriteEffects.None, 0.0f);
SpriteBatch.End();
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritebatch.draw.aspx
You could also load pre-rotated copies of the images, but you'll probably get the usual Premature Optimization lecture.
If you want to rotate only Texture2D field without changing anything in the Draw method, You can use this (it rotates input 90 degrees clockwise):
public static Texture2D RotateTexture90Deegrees(Texture2D input)
{
Texture2D rotated = null;
if (input != null)
{
rotated = new Texture2D(input.GraphicsDevice, input.Width, input.Height);
Color[] data = new Color[input.Width * input.Height];
Color[] rotated_data = new Color[data.Length];
input.GetData<Color>(data);
var Xcounter = 1;
var Ycounter = 0;
for (int i = 0; i < data.Length; i++)
{
rotated_data[i] = data[((input.Width * Xcounter)-1) - Ycounter];
Xcounter += 1;
if (Xcounter > input.Width)
{
Xcounter = 1;
Ycounter += 1;
}
}
rotated.SetData<Color>(rotated_data);
}
return rotated;
}
Related
So as the title says I'm trying to map properly a octahedron sphere using a 3D Perlin Noise as a procedural texture.
I suppose it has something to do about the UVs or about the edges vertices of the texture (left, right, probably even top and down). It's a texture with size 512*512, but it can be 1024*1024.
I've been documentating, trying other techniques, using normal maps, tangets, etc but i still can't figure out how to solve that seam (keep in mind it should be procedurally generated) to generate a surface around the sphere to update it during runtime (in that way I can change the noise (shape of the terrain) as well as the colours).
By the way, when I do the same with a prepared texture (1024*512) with the edges properly corrected the seam disappear, but what I want is the ability to change it in run time (can survive without it but would be nice to have it)
private void OnEnable()
{
if(autoUpdateTexture)
{
if (texture == null)
{
texture = new Texture2D(resolution, resolution, TextureFormat.RGB24, true);
texture.name = "Procedural Texture";
texture.wrapMode = TextureWrapMode.Repeat;
texture.filterMode = FilterMode.Trilinear;
texture.anisoLevel = 9;
GetComponent<MeshRenderer>().sharedMaterial.mainTexture = texture;
}
FillTexture();
}
}
public void FillTexture()
{
if (texture.width != resolution)
{
texture.Resize(resolution, resolution);
}
Vector3 point00 = transform.TransformPoint(new Vector3(-0.5f, -0.5f));
Vector3 point10 = transform.TransformPoint(new Vector3(0.5f, -0.5f));
Vector3 point01 = transform.TransformPoint(new Vector3(-0.5f, 0.5f));
Vector3 point11 = transform.TransformPoint(new Vector3(0.5f, 0.5f));
NoiseMethod method = Noise.noiseMethods[(int)type][dimensions - 1];
float stepSize = 1f / resolution;
for (int y = 0; y < resolution; y++)
{
Vector3 point0 = Vector3.Lerp(point00, point01, (y + 0.5f) * stepSize);
Vector3 point1 = Vector3.Lerp(point10, point11, (y + 0.5f) * stepSize);
for (int x = 0; x < resolution; x++)
{
Vector3 point = Vector3.Lerp(point0, point1, (x + 0.5f) * stepSize);
float sample = Noise.Sum(method, point, frequency, octaves, lacunarity, persistence);
if (type != NoiseMethodType.Value)
{
sample = sample * 0.5f + 0.5f;
}
texture.SetPixel(x, y, coloring.Evaluate(sample));
}
}
texture.Apply();
}
So, I have 2 images, one showing the 3D generated noise in the sphere (when I save the textue to png it just goes to 2D, something obvious)
And the other one, showing that 3D noise IN the sphere with a seam at the edges, so the thing is get that 3D noise in the sphere without the seam.
If you need any more related info, please let me know, as this is giving me a nice headache.
procedural texture in 2D
3D noise on sphere
Yo, Hi everybody
Is there any Way to draw a circle? I don't want to use a Texture/sprite to draw a circle Because the Player is the Circle so the Circle Should move ... and also I'm Trying to make it so the Player/Circle's Size gets bigger and bigger When he eats some food blablabla...
anyways, if anybody knows how to do it please Tell me.
OTHERWISE : IS THERE A WAY TO CHANGE A TEXTURE HEIGHT / WIDTH , THEN I WILL MAKE A SIMPLE CIRCLE TEXTURE AND CHANGE HEIGHT / WIDTH OF IT.
Thanks.
You can use 3D primitives like 'Someone' :> already posted or use the C3.XNA.Primitives2D libary where you can use a extension for SpriteBatch to draw a circle
public static void DrawCircle(this SpriteBatch spriteBatch, Vector2 center, float radius, int sides, Color color, float thickness);
If you use the same value for radius and thickness the circle appears filled.
I didn't find the offizial download link, but there are also uploads at sourceforge.
Also you can generate a circle dynamically via code like:
public static Texture2D GenerateCircleTexture(GraphicsDevice graphicsDevice, int radius, Color color, float sharpness)
{
int diameter = radius * 2;
Texture2D circleTexture = new Texture2D(graphicsDevice, diameter, diameter, false, SurfaceFormat.Color);
Color[] colorData = new Color[circleTexture.Width * circleTexture.Height];
Vector2 center = new Vector2(radius);
for (int colIndex = 0; colIndex < circleTexture.Width; colIndex++)
{
for (int rowIndex = 0; rowIndex < circleTexture.Height; rowIndex++)
{
Vector2 position = new Vector2(colIndex, rowIndex);
float distance = Vector2.Distance(center, position);
// hermite iterpolation
float x = distance / diameter;
float edge0 = (radius * sharpness) / (float)diameter;
float edge1 = radius / (float)diameter;
float temp = MathHelper.Clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
float result = temp * temp * (3.0f - 2.0f * temp);
colorData[rowIndex * circleTexture.Width + colIndex] = color * (1f - result);
}
}
circleTexture.SetData<Color>(colorData);
return circleTexture;
}
Sharpness below 1f blurs the circle.
The only way to draw primitives (e.g. circles) is in 3D:
https://msdn.microsoft.com/en-us/library/bb196414.aspx
Or you can load a texture that is 1*1, stretch it into a line and then use a bunch of those lines to make a circle.
Use:
public void Draw (
Texture2D texture,
Vector2 position,
Nullable<Rectangle> sourceRectangle,
Color color,
float rotation,
Vector2 origin,
Vector2 scale,
SpriteEffects effects,
float layerDepth
)
to stretch the texture.
Or you can just use a circle texture and stretch it.
If you are making something like agar.io then you might want to use a texture combined with the circle primitive so you can make the circle 'wobbly'.
I wanted to know if writing points using a for loop in the begin end batch works or not, so I read up on a sphere algorithm and produced this based on my reading. There are some problems with it as you can see below in the output screen capture. My goal is to produce a sphere procedurally and then modify it at runtime.
but I would like to set my goal on the short-term and figure out why the faces are not correct. anyone have any ideas?
I've got this code:
private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e)
{
// Get the OpenGL object.
OpenGL gl = openGLControl.OpenGL;
// Clear the color and depth buffer.
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
// Load the identity matrix.
gl.LoadIdentity();
// Rotate around the Y axis.
gl.Rotate(rotation, 0.0f, 1.0f, 0.0f);
//Draw a ball
//Drawing Mode
gl.PolygonMode(SharpGL.Enumerations.FaceMode.FrontAndBack, SharpGL.Enumerations.PolygonMode.Lines);
//ball fields
double radius = 4.0d;
const double DEGREE = Math.PI/11.25;
double x = 0;
double y = 0;
double z = 0;
// ball batch
gl.Begin(OpenGL.GL_TRIANGLE_STRIP_ADJACENCY);
for (double j = 0.0d; j < Math.PI; j = j +DEGREE)
{
for (double i = 0; i < 2 * Math.PI; i = i + DEGREE)
{
x = radius * Math.Cos(i) * Math.Sin(j);
y = radius * Math.Sin(j) * Math.Sin(i);
z = radius * Math.Cos(j);
gl.Color(Math.Abs(x + y), Math.Abs(y + z), Math.Abs(z + x));
gl.Vertex(x, y, z);
}
}
gl.End();
// Nudge the rotation.
rotation += 3.0f;
}
i am trying to crop a texture2d in xna. i have found the following code which will crop the image on the top and right sides, i have played around with the code and cannot figure a way to crop all sides at a specific interval. below is the code i have been trying to modify:
any help or ideas would be much appreciated.
Rectangle area = new Rectangle(0, 0, 580, 480);
Texture2D cropped = new Texture2D(heightMap1.GraphicsDevice, area.Width, area.Height);
Color[] data = new Color[heightMap1.Width * heightMap1.Height];
Color[] cropData = new Color[cropped.Width * cropped.Height];
heightMap1.GetData(data);
int index = 0;
for (int y = 0; y < area.Y + area.Height; y++) // for each row
{
for (int x = 0; x < area.X + area.Width; x++) // for each column
{
cropData[index] = data[x + (y * heightMap1.Width)];
index++;
}
}
cropped.SetData(cropData);
Here is the code to crop a texture. Note that the GetData method can already select rectangular subsection of the image - there is no need to manually crop.
// Get your texture
Texture2D texture = Content.Load<Texture2D>("myTexture");
// Calculate the cropped boundary
Rectangle newBounds = texture.Bounds;
const int resizeBy = 20;
newBounds.X += resizeBy;
newBounds.Y += resizeBy;
newBounds.Width -= resizeBy * 2;
newBounds.Height -= resizeBy * 2;
// Create a new texture of the desired size
Texture2D croppedTexture = new Texture2D(GraphicsDevice, newBounds.Width, newBounds.Height);
// Copy the data from the cropped region into a buffer, then into the new texture
Color[] data = new Color[newBounds.Width * newBounds.Height];
texture.GetData(0, newBounds, data, 0, newBounds.Width * newBounds.Height);
croppedTexture.SetData(data);
Of course, keep in mind that SpriteBatch.Draw can take a sourceRectangle parameter, so you may not even need to copy the texture data around at all! Just use a subsection of the original texture. For example:
spriteBatch.Draw(texture, Vector2.Zero, newBounds, Color.White);
(Where newBounds is calculated in the same way as in the first code listing.)
I have some problems with collision. I want to ge coords of a sprite that can be rotated scaled or whatever. It's similiar to Riemers guide, but he's getting a collision of two sprites and I only need those points where alpha is zero.
Better see source:
public Color[,] TextureTo2DArray(Texture2D texture) // to get color array
{
Color[] colors1D = new Color[texture.Width * texture.Height];
texture.GetData(colors1D);
Color[,] colors2D = new Color[texture.Width, texture.Height];
for (int x = 0; x < texture.Width; x++)
for (int y = 0; y < texture.Height; y++)
colors2D[x, y] = colors1D[x + y * texture.Width];
return colors2D;
}
With color is pretty easy, but here is the part where I get points:
public Vector2 TexturePos(Color[,] Color, Matrix matrix)
{
int width1 = Color.GetLength(0);
int height1 = Color.GetLength(1);
for (int x = 0; x < width1; x++)
{
for (int y = 0; y < height1; y++)
{
Vector2 pos1 = new Vector2(x, y);
if (Color[x, y].A > 0)
{
Vector2 screenPos = Vector2.Transform(pos1, matrix);
return screenPos;
}
}
}
return new Vector2(-1, -1);
}
And for matrix I'm using this:
Matrix matrix =
Matrix.CreateTranslation(new Vector3(origin, 0)) *
Matrix.CreateRotationZ(MathHelper.ToRadians(rotation))*
Matrix.CreateScale(scale) *
Matrix.CreateTranslation(new Vector3(pos, 0));
Sprite is rectangular but i get circular movement: I'm rotating it (rotation += 0,5), adding gravity and making it collide with some y value:
Pos.Y += 5;
if (Position.Y >= 200)
BoxPos.Y -= 5;
And I get that it rotates as a circle colliding a line, but not as a rectangle.
Is this normal? Maybe I need some fixes in source?
"That method is supposed to get a position of a pixel (in sprite) that is not transperent but is rotated, scaled (depending on sprite)."
You need to have a look at this:
http://create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel_transformed
This is a great article about 2D collisions in XNA and has an example method that performs 2D collision detection for a Scaled & Rotated set of sprites.