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
Related
I'm trying to generate a circular mesh made up of triangles with a common center at the center of the circle.
The mesh is generated properly, but the UVs are not and I am having some trouble understanding how to add them.
I assumed I would just copy the vertexes' pattern, but it didn't work out.
Here is the function:
private void _MakeMesh(int sides, float radius = 0.5f)
{
m_LiquidMesh.Clear();
float angleStep = 360.0f / (float) sides;
List<Vector3> vertexes = new List<Vector3>();
List<int> triangles = new List<int>();
List<Vector2> uvs = new List<Vector2>();
Quaternion rotation = Quaternion.Euler(0.0f, angleStep, 0.0f);
// Make first triangle.
vertexes.Add(new Vector3(0.0f, 0.0f, 0.0f));
vertexes.Add(new Vector3(radius, 0.0f, 0.0f));
vertexes.Add(rotation * vertexes[1]);
// First UV ??
uvs.Add(new Vector2(0, 0));
uvs.Add(new Vector2(1, 0));
uvs.Add(rotation * uvs[1]);
// Add triangle indices.
triangles.Add(0);
triangles.Add(1);
triangles.Add(2);
for (int i = 0; i < sides - 1; i++)
{
triangles.Add(0);
triangles.Add(vertexes.Count - 1);
triangles.Add(vertexes.Count);
// UV ??
vertexes.Add(rotation * vertexes[vertexes.Count - 1]);
}
m_LiquidMesh.vertices = vertexes.ToArray();
m_LiquidMesh.triangles = triangles.ToArray();
m_LiquidMesh.uv = uvs.ToArray();
m_LiquidMesh.RecalculateNormals();
m_LiquidMesh.RecalculateBounds();
Debug.Log("<color=yellow>Liquid mesh created</color>");
}
How does mapping UV work in a case like this?
Edit: I'm trying to use this circle as an effect of something flowing outwards from the center (think: liquid mesh for a brewing pot)
This is an old post, but maybe someone else will benefit from my solution.
So basically I gave my center point the center of the uv (0.5, 0.5) and then used the used circle formula to give every other point the uv coordinate. But of course I had to remap the cos and sin results from -1..1 to 0..1 and everything is working great.
Vector2[] uv = new Vector2[vertices.Length];
uv[uv.Length - 1] = new Vector2(0.5f, 0.5f);
for (int i = 0; i < uv.Length - 1; i++)
{
float radians = (float) i / (uv.Length - 1) * 2 * Mathf.PI;
uv[i] = new Vector2(Mathf.Cos(radians).Remap(-1f, 1f, 0f, 1f), Mathf.Sin(radians).Remap(-1f, 1f, 0f, 1f));
}
mesh.uv = uv;
Where the remap is an extension like this and it basically take a value in a range and remaps it to another range (in this case from -1..1 to 0..1):
public static float Remap(this float value, float from1, float to1, float from2, float to2) {
return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
}
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'm developing a game engine in c# and am using BulletSharp for physics. It's working well except with cubes:
http://i.stack.imgur.com/EPfrw.png
(The Axis-Aligned Bounding box is the transparent red, the model is the white)
At rest, the stand on their edges. Because I'm loading from Collada models, I am creating a ConvexHullShape() and adding the data as a vector cloud. While using BoxShape() would be more efficient (and work correctly), I cannot as it is not guaranteed that all models are cubes. I cannot figure out why they rest on vertices and not on the flat edges. Is my implementation of ConvexHullShape wrong or do I need to use a different type of shape (for the physics to work correctly)?
public RigidBody AddDynamicGeometry(ColladaGeometry geometry, Matrix4 transform)
{
List<Vector3> points = new List<Vector3>();
foreach (Triangle tri in geometry.triangles)
{
points.Add(tri.vertices[0]);
points.Add(tri.vertices[1]);
points.Add(tri.vertices[2]);
}
CollisionShape shape = new ConvexHullShape(points);
shape.UserObject = geometry;
collisionShapes.Add(shape);
RigidBody body = CreateRigidBody(geometry.triangles.Count * 10, transform, shape);
return body;
}
public RigidBody CreateRigidBody(float mass, Matrix4 startTransform, CollisionShape shape)
{
bool isDynamic = (mass != 0.0f);
Vector3 localInertia = Vector3.Zero;
if (isDynamic)
shape.CalculateLocalInertia(mass, out localInertia);
DefaultMotionState myMotionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
RigidBody body = new RigidBody(rbInfo);
physics_world.AddRigidBody(body);
return body;
}
ConvexHullShape expects the center of mass (COM) to be (0,0,0), but the cube is offset from the center, making it tilt towards the corner.
You can find the correct COM with ConvexTriangleMeshShape.CalculatePrincipalAxisTransform. Then you could subtract the COM from each vertex to bring the COM back to 0. However, it's easier to create a CompoundShape with a local center for the cube.
// Create a ConvexTriangleMeshShape from the points
const int indexStride = 3 * sizeof(int);
const int vertexStride = 12;
int vertexCount = points.Count;
int indexCount = vertexCount / 3;
TriangleIndexVertexArray vertexArray = new TriangleIndexVertexArray();
IndexedMesh mesh = new IndexedMesh();
mesh.Allocate(vertexCount, vertexStride, indexCount, indexStride);
Vector3Array vdata = mesh.Vertices;
IntArray idata = mesh.TriangleIndices;
for (int i = 0; i < vertexCount; i++)
{
vdata[i] = points[i];
idata[i] = i;
}
vertexArray.AddIndexedMesh(mesh);
ConvexTriangleMeshShape shape = new ConvexTriangleMeshShape(vertexArray, true);
// Calculate center of mass
Matrix center = Matrix.Identity;
Vector3 inertia;
float volume;
shape.CalculatePrincipalAxisTransform(ref center, out inertia, out volume);
// Create a CompoundShape with COM offset
CompoundShape compound = new CompoundShape();
compound.AddChildShape(Matrix.Invert(center), shape);
Note: ConvexTriangleMeshShape.CalculatePrincipalAxisTransform works in SVN trunk, but not in BulletSharp 2.82. There will be a bugfix release soon.
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;
}
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.