Unity3d render texture based on position - c#

I'm currently trying to create a container in Unity with multiple quads inside, and am looking for a way to stop parts of the quad that fall outside of the containers bounds from being rendered?
I just spent twenty minutes trying to fiqure out how to explain the problem properly (and failed) so created this pretty picture instead. The red line represents the bounds with the black squares representing my textured quads.

Try this:
private Rect ClipRectToScreen (Rect input)
{
// Special handling for screen reading of render texture so it always stay in visible area.
// Will throw error withoud this fix.
Rect r;
r = new Rect (input.x, (Screen.height - input.y - input.height) , input.width, input.height);
if (r.x < 0f) {
r.width = r.width - UnityEngine.Mathf.Abs (r.x);
r.x = 0f;
// Debug.Log ("x < 0");
}
if (r.y < 0f) {
r.height = r.height - UnityEngine.Mathf.Abs (r.y);
r.y = 0f;
// Debug.Log ("y < 0");
}
if (r.x > Screen.width) {
r.width = r.width - UnityEngine.Mathf.Abs (r.x);
r.x = 0f;
// Debug.Log ("x > Screen.width");
}
if (r.y > Screen.height) {
r.height = r.height - UnityEngine.Mathf.Abs (r.y);
r.y = 0f;
// Debug.Log ("y > Screen.height");
}
if ((r.x + r.width) > Screen.width) {
r.width = Screen.width - r.x;
// Debug.Log ("r.x + r.width > Screen.width");
}
if ((r.y + r.height) > Screen.height) {
r.height = Screen.height - r.y;
// Debug.Log ("r.y + r.height > Screen.height");
}
return r;
}

Related

Screen size based tooltip with offset

Hi guys im trying to make a tooltip window for some items in the game im making. And for the love of god i cant figure out how to setup a screen based offset for the tooltip. Atm im using this (code no.1) after 2 sec turns on the tooltip gameobject (called StatDisplay) and it works on 16x9 resolution but after changing the resolution the tooltip is too far away from the main object. I tried it with mouse position (code 2) and im running into the same problem with the offset, its decreasing on higher resolutions and in smaller ones the offset is too big. Any ideas on how to fix this ? (i was thinking about making a variable that changes based on screen size but cant figure out a way...)
Code 1:
bool hovering = false;
public GameObject StatDisplay;
IEnumerator StartCountdown()
{
RectTransform rc = StatDisplay.GetComponent<RectTransform>();
RectTransform rc2 = this.GetComponent<RectTransform>();
int time = 1;
while ((time > 0) && (hovering == true))
{
yield return new WaitForSeconds(1.0f);
time--;
}
if ((time == 0) && (hovering == true))
{
if (Input.mousePosition.x > (Screen.width / 2))
{
if (Input.mousePosition.y > (Screen.height / 2))
{
//Debug.Log("Top right");
StatDisplay.transform.position = new Vector3(-rc.rect.width / 2 + this.transform.position.x + rc2.rect.width / 2, -rc.rect.height / 2 + this.transform.position.y - rc2.rect.height / 2, 0);
}
else
{
//Debug.Log("Bottom right");
StatDisplay.transform.position = new Vector3(- rc.rect.width / 2 + this.transform.position.x + rc2.rect.width / 2, rc.rect.height / 2 + this.transform.position.y + rc2.rect.height / 2, 0);
}
}
else
{
if (Input.mousePosition.y > (Screen.height / 2))
{
//Debug.Log("Top Left");
StatDisplay.transform.position = new Vector3(rc.rect.width / 2 + this.transform.position.x - rc2.rect.width / 2, - rc.rect.height / 2 + this.transform.position.y - rc2.rect.height / 2, 0);
}
else
{
//Debug.Log("Bottom Left");
StatDisplay.transform.position = new Vector3(rc.rect.width / 2 + this.transform.position.x - rc2.rect.width / 2, rc.rect.height / 2 + this.transform.position.y + rc2.rect.height / 2, 0);
}
}
StatDisplay.SetActive(true);
}
}
public void Enter()
{
hovering = true;
StartCoroutine(StartCountdown());
}
public void Exit()
{
hovering = false;
StatDisplay.SetActive(false);
}
Code 2:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HoverAtCursorPosition : MonoBehaviour
{
RectTransform rt;
CanvasGroup cg;
float Obwidth;
float Obheight;
Vector3 MousePoz = new Vector3();
private void Start()
{
rt = GetComponent<RectTransform>();
cg = GetComponent<CanvasGroup>();
}
private void OnEnable()
{
PositionFunction();
}
private void OnDisable()
{
cg.alpha = 0;
}
void Update()
{
Obwidth = rt.rect.width + 20f;
Obheight = rt.rect.height + 20f;
//Debug.Log("X: " + Screen.width / rt.rect.width);
//Debug.Log("Y: " + Screen.height / rt.rect.height);
MousePoz = Camera.main.ScreenToViewportPoint(Input.mousePosition);
PositionFunction();
if (cg.alpha != 1)
{
if (gameObject.activeSelf == true)
{
cg.alpha += 0.1f;
}
}
}
void PositionFunction()
{
if (Input.mousePosition.x > (Screen.width / 2))
{
if (Input.mousePosition.y > (Screen.height / 2))
{
//Debug.Log("Top right");
transform.position = new Vector3(MousePoz.x * Screen.width - Obwidth / 2, MousePoz.y * Screen.height - Obheight / 2);
}
else
{
//Debug.Log("Bottom right");
transform.position = new Vector3(MousePoz.x * Screen.width - Obwidth / 2, MousePoz.y * Screen.height + Obheight / 2);
}
}
else
{
if (Input.mousePosition.y > (Screen.height / 2))
{
//Debug.Log("Top Left");
transform.position = new Vector3(MousePoz.x * Screen.width + Obwidth / 2, MousePoz.y * Screen.height - Obheight / 2);
}
else
{
//Debug.Log("Bottom Left");
transform.position = new Vector3(MousePoz.x * Screen.width + Obwidth / 2, MousePoz.y * Screen.height + Obheight / 2);
}
}
}
}
class level var:
bool isVis=false;
void OnGUI(){
if (isVis)
{
GUI.Box(new Rect(Input.mousePosition.x + 2, Screen.height - Input.mousePosition.y + 2, 128, 72), "Tool Tip Text");
}
}
private void OnMouseEnter()
{
isVis = true;
}
private void OnMouseExit()
{
isVis = false;
}
throw this on your object you want a tool tip for, then you can make some adjustments. this will give you a box with the text "Tool Tip Text" at the mouse position, while you are mouse over the object. your object will need a collider.
more to the point of your question: you are looking for this line:
new Rect(Input.mousePosition.x + 2, Screen.height - Input.mousePosition.y + 2, 128, 72)
to get the correct y position in your endeavor you need to subtract the mousePosition.y from Screen.Height
its also important to note the +2, as if you draw right at the mouse it will stutter between the tooltip and the cursor
as i said below if you store the tool tip rect in a variable, thats set in Update()
in your OnGUI you can do this:
GUI.Box(myRect, "Tool Tip Text");
GUI.DrawTexture(new Rect(myRect.x,myRect.y+20,64,64),Resources.Load("Sprites/sample.png")) ;
(the load method will grab the image, sample.png from your Resources/Sprites folder, if you dont have that folder you can make it, or change the path, but the path has to be in a folder called Resources
you can also do
GUI.Label(new Rect(myRect.x,myRect.y+84,myRect.width,24),"Item Description")) ;
the best part is, you can load a custom GUI skin, and set your own styles, and change each GUI element dynamically. this means if you want a white title, and a gold description and a border around your image, it's a simple thing. if you want some sample styles let me know!
Ok while playing around i found a way to fix my code
rt = this.GetComponent<RectTransform>();
float RealWidth = rt.rect.width / Screen.width;
float RealHeight = rt.rect.height / Screen.height;
rt is on the component thats has its anchor set to stretch on x and y (Rect transform > icon on the left > alt + icon at bottom right)
it seems like the real screen width and the width of the rect of an object are not the same even if its stretched to fit the whole screen. its always off by +-10-20% (not sure if its bc of canvas settings or what)... well whatever
new Vector3(Input.mousePosition.x * RealWidth, Input.mousePosition.y * RealHeight, 0)
this vector will give you the right position on all the resolutions. well it does for me... it might help someone in with a similar problem

How to move the ball in different directions?

Now when I hit spacebar it will go left or right, I want the ball to go straight first time.Then when the ball hit a wall, block or line after that I want the ball to go random directions with "-1" somehow. This is my first school game project, it's a one line pong game.
Edit: Edit I've added "boll_speed.X = random.Next(-1, 1);", and that works perfectly!
linje = line
liv = lives
boll = ball
poang = points
I don't use "blockröd = blockred" right now
blockgrön = blockgreen
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteFont spritefont;
Texture2D linje_texture;
Texture2D boll_texture;
Texture2D blockröd_texture;
Texture2D blockgrön_texture;
Texture2D gameover_texture;
Rectangle linje_rect;
Rectangle boll_rect;
Rectangle blockröd_rect;
Rectangle blockgrön_rect;
Rectangle gameover_rect;
Vector2 linje_speed;
Vector2 boll_speed;
Random random;
int liv;
int poang;
int highscore;
List<Rectangle> block = new List<Rectangle>();
bool Start = false;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 760;
graphics.PreferredBackBufferHeight = 620;
}
protected override void Initialize()
{
linje_speed.X = 5f;
boll_speed.X = boll_speed.X = random.Next(-1, 1);
boll_speed.Y = 6f;
liv = 3;
poang = 0;
random = new Random();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
spritefont = Content.Load<SpriteFont>("Fonts/Myfont");
linje_texture = Content.Load<Texture2D>("Pics/linje-lång");
boll_texture = Content.Load<Texture2D>("Pics/boll");
blockgrön_texture = Content.Load<Texture2D>("Pics/block-grön");
blockröd_texture = Content.Load<Texture2D>("Pics/block-röd");
gameover_texture = Content.Load<Texture2D>("Pics/GameOver");
linje_rect = new Rectangle((Window.ClientBounds.Width - linje_texture.Width) / 2, 580, linje_texture.Width, linje_texture.Height);
boll_rect = new Rectangle((Window.ClientBounds.Width - boll_texture.Width) / 2, 556, boll_texture.Width, boll_texture.Height);
gameover_rect = new Rectangle((Window.ClientBounds.Width / 2) - (gameover_texture.Width / 2), (Window.ClientBounds.Height / 2) - gameover_texture.Height / 2, gameover_texture.Width, gameover_texture.Height);
block.Add(blockgrön_rect);
block.Add(blockröd_rect);
for (int i = 1; i < 5; i++)
{
for (int g = 1; g < 13; g++)
{
block.Add(new Rectangle((g * 63) - 60, (i * 40), blockgrön_texture.Width, blockgrön_texture.Height));
}
}
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if (Start == true)
{
boll_rect.X += (int)boll_speed.X;
boll_rect.Y += (int)boll_speed.Y;
}
if(Start == false)
{
boll_rect.X = linje_rect.X + ((linje_texture.Width / 2) - (boll_texture.Width / 2));
}
if (boll_rect.X > Window.ClientBounds.Width - boll_texture.Width || boll_rect.X < 0)
boll_speed.X *= -1;
if (boll_rect.Y > Window.ClientBounds.Height - boll_texture.Height || boll_rect.Y < 0)
boll_speed.Y *= -1;
if (boll_rect.Y > Window.ClientBounds.Height - boll_texture.Height)
{
liv -= 1;
Start = false;
boll_rect.X = (Window.ClientBounds.Width - boll_texture.Width) / 2;
boll_rect.Y = 556;
linje_rect.X = (Window.ClientBounds.Width - linje_texture.Width) / 2;
linje_rect.Y = 580;
}
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
{
linje_rect.X -= (int)linje_speed.X;
}
else if (ks.IsKeyDown(Keys.Right))
{
linje_rect.X += (int)linje_speed.X;
}
else if (ks.IsKeyDown(Keys.Space))
{
Start = true;
}
if (linje_rect.X > Window.ClientBounds.Width - linje_texture.Width)
linje_rect.X = (Window.ClientBounds.Width - linje_texture.Width);
if (linje_rect.X < 0)
linje_rect.X = 0;
if (linje_rect.Intersects(boll_rect))
{
boll_speed.Y *= -1;
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
if (liv > 0)
{
spriteBatch.Draw(linje_texture, linje_rect, Color.White);
spriteBatch.Draw(boll_texture, boll_rect, Color.White);
spriteBatch.DrawString(spritefont, "Liv kvar: " + liv, Vector2.Zero, Color.White);
spriteBatch.DrawString(spritefont, "Points: " + poang, new Vector2(350, 0), Color.White);
spriteBatch.DrawString(spritefont, "Highscore: " + highscore, new Vector2(660, 0), Color.White);
foreach (Rectangle g in block)
{
spriteBatch.Draw(blockgrön_texture, g, Color.White);
}
}
if (liv == 0)
{
spriteBatch.Draw(gameover_texture, gameover_rect, Color.White);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
Having trouble with these parts:
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if (Start == true)
{
boll_rect.X += (int)boll_speed.X;
boll_rect.Y += (int)boll_speed.Y;
}
if (boll_rect.X > Window.ClientBounds.Width - boll_texture.Width || boll_rect.X < 0)
boll_speed.X *= -1;
if (boll_rect.Y > Window.ClientBounds.Height - boll_texture.Height || boll_rect.Y < 0)
boll_speed.Y *= -1;
else if (ks.IsKeyDown(Keys.Space))
{
Start = true;
}
if (linje_rect.Intersects(boll_rect))
{
boll_speed.Y *= -1;
boll_speed.Y += random.Next(-100, 101) / 100.0f;
boll_speed.X *= -1;
boll_speed.X += random.Next(-100, 101) / 100.0f;
}
I will give you the generic idea. Please adapt it to your example
Lets say you want to move to all directions on the board, now imagine your board as a bi-dimensional array(all your pixels has an x,y representation on that board)
The (0,0) marks the left upper corner of your board, and your (width, height) mark the lower right corner. Your ball is on the middle of the board on the (x, y) position, where x > 0 and x < width(of the board) and y > 0 and y < height.
You have 8 different directions base on the picture below
Now it is time to translate those directions to a logical structure. You need to create an array for that, lets say we want to start from the NW direction. I will create an array with the numbers that you need to add to your (x, y) position in order to keep going in the direction you choose. If you see I am creating a bidimentional array
Now this is the pseudocode for your idea:
int[,] directions = new int[,]{{-1,-1,-1,0,1,1,1,0}, {-1,0,1,1,1,0,-1,-1}};
public void Move(Game game)
{
Point currentPosition = GetYourCurrentPosition(); //the x, y
int direction = GetYourRandomDirection() //this should be a random number between 0 and 7, beucase the array for directions has 8 positions.
int xDirection = directions[0, direction];
int yDirection = directions[1, direction];
//move inside the board forever
while(true)
{
while(ICanMoveTo(currentPosition.X + xDirection, currentPosition.Y + yDirection)
{
//keep moving on the same direction
currentPosition.X += xDirection;
currentPosition.Y += yDirection;
}
//if you can't move anymore in the same direction, then change
direction = GetYourRandomDirection();
xDirection = directions[0, direction];
yDirection = directions[1, direction];
}
}
Random.Next(-1) should give you out of bounds error.
You can use something like Random.Next(-200, 0)/100.0f, which will return a negative number between -2 and 0 (including -2, excluding 0).
But notice that this multiplication will lead to slowdown of ball over time. It might speed up to double of current speed, but it can slow down to nearly 0 in a single step. So I would rather first invert ball speed in y direction and keep it the same in x if you hit horizontal lines, and invert in x and keep in y if you hit vertical lines. Then do a random addition of a zero-means constant.
boll_speed.Y *= -1;
boll_speed.Y += random.Next(-100, 101)/100.0f; // Add random number between -1 and 1 with 0.01 precision.
// and nearly the same for X. Depending on the lines hit.
I'm thinking you mean you want the ball to change directions randomly when it hits the window boundaries or line. If so:
You're using constant values for your direction changes. Add a randomizer to multiply your boll_speed by.
For example, in pseudocode, instead of -1, do random(-1).

XNA Loading Models

I am pretty new to the 3D side of XNA and am converting a 2D game.
Its basically designed as a grid and I am drawing with the code below. This works but is a bit laggy, am I doing this completely wrong? Presumably there shouldn't be much lag at this point when we are only talking about a few small models.
protected override void Draw(GameTime gameTime)
{
fpsTimer += gameTime.ElapsedGameTime;
fpsCount++;
if (fpsTimer >= TimeSpan.FromSeconds(1))
{ fpsTimer = TimeSpan.FromSeconds(0); fps = fpsCount; fpsCount = 0; }
GraphicsDevice.Clear(Color.CornflowerBlue);
projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 1000.0f);
world = Matrix.CreateTranslation(new Vector3(0, 0, 0));
view = Matrix.CreateLookAt(new Vector3(xPos, yPos, zHeight), new Vector3(xPos, yPos + zRotation, 0), new Vector3(0, 5, 0));
// DRAW OBJECTS ON MAP
drawMap(view, world, projection);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
spriteBatch.DrawString(font, "" + fps, new Vector2(100, 100), Color.Black);
spriteBatch.End();
base.Draw(gameTime);
}
private void drawMap(Matrix view, Matrix world, Matrix projection)
{
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
int scale = Globals.scale;
int screenWidthScale = Globals.screenwidth / scale;
int screenHeightScale = Globals.screenheight / scale;
int mapXtile = Convert.ToInt32(xPos/2);
int mapYtile = Convert.ToInt32(yPos/2);
for (int i = Convert.ToInt32(xPos/2) - 30; i < Convert.ToInt32(xPos/2) + 30; i++)
{
for (int a = Convert.ToInt32(yPos/2); a < Convert.ToInt32(yPos/2) + 50; a++)
{
if (mapXtile > 0 && mapYtile > 0 && mapXtile < Globals.mapsizex && mapYtile < Globals.mapsizey)
{
int currentTile = Globals.levelArray[mapXtile, mapYtile].TyleType;
// DRAW TREES
if (currentTile == tyleType.tree)
{
if (Globals.levelArray[mapXtile, mapYtile].typeModifier == 1)
{
Matrix worldMatrix = Matrix.CreateScale(0.8f, 0.8f, 0.8f) * Matrix.CreateRotationX(1.5f) * Matrix.CreateTranslation(new Vector3(i * 2 + 0.2f, a * 2 - 0.4f, -0.1f));
tree.Draw(worldMatrix, view, projection);
}
if (Globals.levelArray[mapXtile, mapYtile].typeModifier == 2)
{
Matrix worldMatrix = Matrix.CreateScale(0.8f, 0.8f, 0.8f) * Matrix.CreateRotationX(1.5f) * Matrix.CreateTranslation(new Vector3(i * 2+0.2f, a * 2-0.4f, -0.1f));
tree2.Draw(worldMatrix, view, projection);
}
}
}
mapYtile = mapYtile + 1;
//mapYtile++;
}
mapXtile = mapXtile + 1;
mapYtile = Convert.ToInt32(yPos / 2);
}
}

Checking if a point is inside a rotated rectangle

I know this question has been asked a few times before, and I have read various posts about this. However I am struggling to get this to work.
bool isClicked()
{
Vector2 origLoc = Location;
Matrix rotationMatrix = Matrix.CreateRotationZ(-Rotation);
Location = new Vector2(0 -(Texture.Width/2), 0 - (Texture.Height/2));
Vector2 rotatedPoint = new Vector2(Game1.mouseState.X, Game1.mouseState.Y);
rotatedPoint = Vector2.Transform(rotatedPoint, rotationMatrix);
if (Game1.mouseState.LeftButton == ButtonState.Pressed &&
rotatedPoint.X > Location.X &&
rotatedPoint.X < Location.X + Texture.Width &&
rotatedPoint.Y > Location.Y &&
rotatedPoint.Y < Location.Y + Texture.Height)
{
Location = origLoc;
return true;
}
Location = origLoc;
return false;
}
Let point P(x,y), and rectangle A(x1,y1), B(x2,y2), C(x3,y3), D(x4,y4).
Calculate the sum of areas of △APD, △DPC, △CPB, △PBA.
If this sum is greater than the area of the rectangle:
Then point P(x,y) is outside the rectangle.
Else it is in or on the rectangle.
The area of each triangle can be calculated using only coordinates with this formula:
Assuming the three points are: A(x,y), B(x,y), C(x,y)...
Area = abs( (Bx * Ay - Ax * By) + (Cx * By - Bx * Cy) + (Ax * Cy - Cx * Ay) ) / 2
I assume that Location is the rectangle's rotation center. If not, please update your answer with an appropriate figure.
What you want to do is expressing the mouse location in the local system of the rectangle. Therfore, you could do the following:
bool isClicked()
{
Matrix rotationMatrix = Matrix.CreateRotationZ(-Rotation);
//difference vector from rotation center to mouse
var localMouse = new Vector2(Game1.mouseState.X, Game1.mouseState.Y) - Location;
//now rotate the mouse
localMouse = Vector2.Transform(localMouse, rotationMatrix);
if (Game1.mouseState.LeftButton == ButtonState.Pressed &&
rotatedPoint.X > -Texture.Width / 2 &&
rotatedPoint.X < Texture.Width / 2 &&
rotatedPoint.Y > -Texture.Height / 2 &&
rotatedPoint.Y < Texture.Height / 2)
{
return true;
}
return false;
}
Additionally, you may want to move the check if the mouse is pressed to the beginning of the method. If it is not pressed, you don't have to calculate the transformation etc.

Optimizing a formula to create a triangle from arbitrary points

I think a little background will help before I get into my question. What I'm doing is creating my own small 2D physics library in xna, for fun nonetheless. This is also my first independent xna project, and my first time working with the 3D tools, so I may be doing things all wacky. Anyway, I'm currently making a triangle class in which the constructor takes three arbitrary points in the form of Vector2s. In the constructor I have to put these points in clockwise order (so they're not culled) and then find the texture coordinates they should correspond to (since I'm using VertexPositionTextures as my vertices). What I've got works, but it seems very long and complicated. I'm looking for any ways to shorten/simplify the code, which is this:
public PTriangle(Vector2 a, Vector2 b, Vector2 c)
: base()
{
//set up vertices
VertexPositionTexture[] vertices = new VertexPositionTexture[3];
//center vertices around origin
Vector2 center = new Vector2((a.X + b.X + c.X) / 3, (a.Y + b.Y + c.Y) / 3);
Vector2 newA = a - center;
Vector2 newB = b - center;
Vector2 newC = c - center;
//get angle of each vertex (clockwise from -x axis)
double angleA = MathHelper.Pi - Math.Atan((double)(newA.Y / newA.X));
double angleB = MathHelper.Pi - Math.Atan((double)(newB.Y / newB.X));
double angleC = MathHelper.Pi - Math.Atan((double)(newC.Y / newC.X));
if (newA.X < 0)
{
if (newA.Y < 0)
{
angleA += MathHelper.Pi;
}
else
{
angleA -= MathHelper.Pi;
}
}
if (newB.X < 0)
{
if (newB.Y < 0)
{
angleB += MathHelper.Pi;
}
else
{
angleB -= MathHelper.Pi;
}
}
if (newC.X < 0)
{
if (newC.Y < 0)
{
angleC += MathHelper.Pi;
}
else
{
angleC -= MathHelper.Pi;
}
}
//order vertices by angle
Vector2[] newVertices = new Vector2[3];
if (angleA < angleB && angleA < angleC)
{
newVertices[0] = newA;
if (angleB < angleC)
{
newVertices[1] = newB;
newVertices[2] = newC;
}
else
{
newVertices[1] = newC;
newVertices[2] = newB;
}
}
else if (angleB < angleA && angleB < angleC)
{
newVertices[0] = newB;
if (angleA < angleC)
{
newVertices[1] = newA;
newVertices[2] = newC;
}
else
{
newVertices[1] = newC;
newVertices[2] = newA;
}
}
else
{
newVertices[0] = newC;
if (angleA < angleB)
{
newVertices[1] = newA;
newVertices[2] = newB;
}
else
{
newVertices[1] = newB;
newVertices[2] = newA;
}
}
//set positions of vertices
vertices[0].Position = new Vector3(newVertices[0] + center, 0);
vertices[1].Position = new Vector3(newVertices[1] + center, 0);
vertices[2].Position = new Vector3(newVertices[2] + center, 0);
//get width and height of triangle
float minX = 0;
float minY = 0;
float maxX = 0;
float maxY = 0;
foreach (Vector2 vertex in newVertices)
{
if (vertex.X < minX)
{
minX = vertex.X;
}
else if (vertex.X > maxX)
{
maxX = vertex.X;
}
if (vertex.Y < minY)
{
minY = vertex.Y;
}
else if (vertex.Y > maxY)
{
maxY = vertex.Y;
}
}
float width = maxX - minX;
float height = maxY - minY;
//shift triangle so fits in quadrant IV, and set texture coordinates
for (int index = 0; index < newVertices.Length; ++index)
{
newVertices[index].X -= minX;
newVertices[index].Y -= minY;
vertices[index].TextureCoordinate = new Vector2(
newVertices[index].X / width,
1 - (newVertices[index].Y / height));
}
this.Vertices = vertices;
//set up indices
this.Indices = new short[] { 0, 1, 2 };
}
To put the 3 points in clockwise order, you can use counter-clockwise test (or left-turn test) to check the direction of the 3 points.
Pseudocode from Wikipedia
# Three points are a counter-clockwise turn if ccw > 0, clockwise if
# ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
# gives the signed area of the triangle formed by p1, p2 and p3.
function ccw(p1, p2, p3):
return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)
If the 3 points are counter-clockwise, you can just swap the last 2 points to make the 3 points clockwise order.

Categories