i get tired to calculate the volume of 3D object (Cube, Cylinder ...) can any one help
with this problem ? the question is , how to calculate the volume of object from his
coordinates based on triangles. my class don't do well the job , any one help me to
emproove the class ?
thanks
public class Algorithm
{
private Mesh _mesh { get; set; }
public Algorithm(Mesh mesh)
{
_mesh = mesh;
}
private double SignedVolumeOfTriangle(Vector3 p1, Vector3 p2, Vector3 p3)
{
var v321 = p3.X * p2.Y * p1.Z;
var v231 = p2.X * p3.Y * p1.Z;
var v312 = p3.X * p1.Y * p2.Z;
var v132 = p1.X * p3.Y * p2.Z;
var v213 = p2.X * p1.Y * p3.Z;
var v123 = p1.X * p2.Y * p3.Z;
return (1.0 / 6.0) * (-v321 + v231 + v312 - v132 - v213 + v123);
}
public double VolumeOfMesh()
{
double volume = 0.0;
Vector3[] vertices = _mesh.Vertices;
int[] triangles = _mesh.Triangles;
for (int i = 0; i < _mesh.Triangles.Length; i += 3)
{
Vector3 p1 = vertices[triangles[i + 0]];
Vector3 p2 = vertices[triangles[i + 1]];
Vector3 p3 = vertices[triangles[i + 2]];
volume += SignedVolumeOfTriangle(p1, p2, p3);
}
return Math.Abs(volume);
}
}
public class Mesh
{
public Mesh(Vector3[] _vertices,int[] _triangles)
{
Vertices = _vertices;
Triangles = _triangles;
}
public Vector3[] Vertices { get; set; }
public int[] Triangles { get; set; }
}
public class Vector3
{
public Vector3()
{
}
public Vector3(double x,double y,double z)
{
X = x;
Y = y;
Z = z;
}
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
Vector3[] vers = new Vector3[8] {
new Vector3 {X = 5,Y = 5,Z =5},
new Vector3 {X = 15,Y = 5,Z =5},
new Vector3 {X = 15,Y = 15,Z =5},
new Vector3 {X = 5,Y = 15,Z =5},
new Vector3 {X = 5,Y = 5,Z =15},
new Vector3 {X = 15,Y = 5,Z =15},
new Vector3 {X = 15,Y = 15,Z =15},
new Vector3 {X = 5,Y = 15,Z =15},
};
int[] trs = new int[36] { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7,
1, 6, 2, 1, 5, 6, 0, 4, 7, 0, 7, 3,
0, 1, 5, 0, 5, 4, 3, 2, 6,3, 6, 7 };
Mesh mesh = new Mesh(vers, trs);
Algorithm algo = new Algorithm(mesh);
var vol = algo.VolumeOfMesh();
MessageBox.Show(vol.ToString());
}
The result of my test is vol = 666,666 but it should be 1000.
The line
double v132 = (p3.X - basePoint.X) * (p3.Y - basePoint.Y) * (p2.Z - basePoint.Z);
Is not correct according to How to calculate the volume of a 3D mesh object the surface of which is made up triangles it should be (notice the p1.X instead of p3.X):
var v132 = p1.X*p3.Y*p2.Z;
EDIT
Although you marked this answer as correct I tested the code and found more errors.
The triangles are not all facing outward (or inward) by adjusting the triangle indices like this:
0, 1, 2,
0, 2, 3,
4, 6, 5,
4, 7, 6,// adjusted
1, 6, 2,
1, 5, 6,
0, 7, 4,// adjusted
0, 3, 7,// adjusted
0, 5, 1,// adjusted
0, 4, 5,// adjusted
3, 2, 6,
3, 6, 7
all normals face outward. the calculation then returns -1000 the minus depending on the base offset.
Related
I have created a spinning cube and it's working fine except the weird flickering caused by clearing the picturebox.
This is my first 3D project and I have 0 experience in this.
I have recreated javidx9's code in c#
c# Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using static System.Math;
using static _3DTutorial1.Form1.Tools1;
namespace _3DTutorial1
{
public partial class Form1 : Form
{
private static PictureBox pictureBox1 = new PictureBox();
private static mesh meshCube;
//Projection Matrix
private static matrix4x4 matrixProjection;
private static float fNear = 0.1f;
private static float fFar = 1000;
private static float fFov = 90;
private static float fAspectRatio = (float)1000 / 1000;//Height / Width;
private static float fFovRad = 1 / (float)Tan(fFov * 0.5 / 180 * PI);
//Rotation
private static float fTheta = 0;
private static matrix4x4 matrixRotationZ;
private static matrix4x4 matrixRotationX;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Width = 1000;
Height = 1000;
pictureBox1.Dock = DockStyle.Fill;
pictureBox1.BackColor = Color.Black;
Controls.Add(pictureBox1);
timer1.Interval = 20;
meshCube = Create_mesh(
//SOUTH
Create_triangle(Create_vector3d(0, 0, 0), Create_vector3d(0, 1, 0), Create_vector3d(1, 1, 0)),
Create_triangle(Create_vector3d(0, 0, 0), Create_vector3d(1, 1, 0), Create_vector3d(1, 0, 0)),
//EAST
Create_triangle(Create_vector3d(1, 0, 0), Create_vector3d(1, 1, 0), Create_vector3d(1, 1, 1)),
Create_triangle(Create_vector3d(1, 0, 0), Create_vector3d(1, 1, 1), Create_vector3d(1, 0, 1)),
//NORTH
Create_triangle(Create_vector3d(1, 0, 1), Create_vector3d(1, 1, 1), Create_vector3d(0, 1, 1)),
Create_triangle(Create_vector3d(1, 0, 1), Create_vector3d(0, 1, 1), Create_vector3d(0, 0, 1)),
//WEST
Create_triangle(Create_vector3d(0, 0, 1), Create_vector3d(0, 1, 1), Create_vector3d(0, 1, 0)),
Create_triangle(Create_vector3d(0, 0, 1), Create_vector3d(0, 1, 0), Create_vector3d(0, 0, 0)),
//TOP
Create_triangle(Create_vector3d(0, 1, 0), Create_vector3d(0, 1, 1), Create_vector3d(1, 1, 1)),
Create_triangle(Create_vector3d(0, 1, 0), Create_vector3d(1, 1, 1), Create_vector3d(1, 1, 0)),
//BOTTOM
Create_triangle(Create_vector3d(1, 0, 1), Create_vector3d(0, 0, 1), Create_vector3d(0, 0, 0)),
Create_triangle(Create_vector3d(1, 0, 1), Create_vector3d(0, 0, 0), Create_vector3d(1, 0, 0))
);
//Projection Matrix
matrixProjection = Create_matrix4x4(
(0, 0, fAspectRatio * fFovRad),
(1, 1, fFovRad),
(2, 2, fFar / (fFar - fNear)),
(3, 2, (-fFar * fNear) / (fFar - fNear)),
(2, 3, 1),
(3, 3, 0)
);
}
private void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.X)
{
timer1.Start();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Graphics g = pictureBox1.CreateGraphics();
//Rotation
fTheta += 0.01f;
matrixRotationZ = Create_matrix4x4(
(0, 0, (float)Cos(fTheta)),
(0, 1, (float)Sin(fTheta)),
(1, 0, (float)-Sin(fTheta)),
(1, 1, (float)Cos(fTheta)),
(2, 2, 1),
(3, 3, 1)
);
matrixRotationX = Create_matrix4x4(
(0, 0, 1),
(1, 1, (float)Cos(fTheta)),
(1, 2, (float)Sin(fTheta)),
(2, 1, (float)-Sin(fTheta)),
(2, 2, (float)Cos(fTheta)),
(3, 3, 1)
);
//Clear / Draw
List<triangle> Ready2DrawCube = new List<triangle>();
//Calculate Draw
foreach (var item in meshCube.tris)
{
triangle triangleProjected, triangleTranslated, triangleRotatedZ, triangleRotatedZX;
triangleRotatedZ = Create_triangle(Create_vector3d(), Create_vector3d(), Create_vector3d());
triangleRotatedZX = Create_triangle(Create_vector3d(), Create_vector3d(), Create_vector3d());
triangleProjected = Create_triangle(Create_vector3d(), Create_vector3d(), Create_vector3d());
triangleRotatedZ.p[0] = MultiplyMatrixVector(item.p[0], matrixRotationZ);
triangleRotatedZ.p[1] = MultiplyMatrixVector(item.p[1], matrixRotationZ);
triangleRotatedZ.p[2] = MultiplyMatrixVector(item.p[2], matrixRotationZ);
triangleRotatedZX.p[0] = MultiplyMatrixVector(triangleRotatedZ.p[0], matrixRotationX);
triangleRotatedZX.p[1] = MultiplyMatrixVector(triangleRotatedZ.p[1], matrixRotationX);
triangleRotatedZX.p[2] = MultiplyMatrixVector(triangleRotatedZ.p[2], matrixRotationX);
triangleTranslated = triangleRotatedZX;
triangleTranslated.p[0].z = triangleRotatedZX.p[0].z + 3.0f;
triangleTranslated.p[1].z = triangleRotatedZX.p[1].z + 3.0f;
triangleTranslated.p[2].z = triangleRotatedZX.p[2].z + 3.0f;
triangleProjected.p[0] = MultiplyMatrixVector(triangleTranslated.p[0], matrixProjection);
triangleProjected.p[1] = MultiplyMatrixVector(triangleTranslated.p[1], matrixProjection);
triangleProjected.p[2] = MultiplyMatrixVector(triangleTranslated.p[2], matrixProjection);
//Scale into view
triangleProjected.p[0].x += 1; triangleProjected.p[0].y += 1;
triangleProjected.p[1].x += 1; triangleProjected.p[1].y += 1;
triangleProjected.p[2].x += 1; triangleProjected.p[2].y += 1;
triangleProjected.p[0].x *= 0.5f * Width; triangleProjected.p[0].y *= 0.5f * Width;
triangleProjected.p[1].x *= 0.5f * Width; triangleProjected.p[1].y *= 0.5f * Width;
triangleProjected.p[2].x *= 0.5f * Width; triangleProjected.p[2].y *= 0.5f * Width;
//Done
Ready2DrawCube.Add(triangleProjected);
}
//Draw Triangles
g.Clear(Color.Black);
foreach (var item in Ready2DrawCube)
{
DrawTriangle(
(int)item.p[0].x, (int)item.p[0].y,
(int)item.p[1].x, (int)item.p[1].y,
(int)item.p[2].x, (int)item.p[2].y,
Pens.White
);
}
}
public class Tools1
{
private static Graphics g = pictureBox1.CreateGraphics();
public static void DrawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, Pen p)
{
g.DrawLine(p, new Point(x1, y1), new Point(x2, y2));
g.DrawLine(p, new Point(x2, y2), new Point(x3, y3));
g.DrawLine(p, new Point(x3, y3), new Point(x1, y1));
}
public static vector3d MultiplyMatrixVector(vector3d _i, matrix4x4 _m)
{
vector3d o_ = Create_vector3d();
o_.x = _i.x * _m.m[0, 0] + _i.y * _m.m[1, 0] + _i.z * _m.m[2, 0] + _m.m[3, 0];
o_.y = _i.x * _m.m[0, 1] + _i.y * _m.m[1, 1] + _i.z * _m.m[2, 1] + _m.m[3, 1];
o_.z = _i.x * _m.m[0, 2] + _i.y * _m.m[1, 2] + _i.z * _m.m[2, 2] + _m.m[3, 2];
float w = _i.x * _m.m[0, 3] + _i.y * _m.m[1, 3] + _i.z * _m.m[2, 3] + _m.m[3, 3];
if (w != 0)
{
o_.x /= w;
o_.y /= w;
o_.z /= w;
}
return o_;
}
public static vector3d Create_vector3d(float _x = 0, float _y = 0, float _z = 0)
{
vector3d v_ = new vector3d();
v_.x = _x;
v_.y = _y;
v_.z = _z;
return v_;
}
public static triangle Create_triangle(params vector3d[] _p)
{
triangle t_ = new triangle();
t_.p = _p;
return t_;
}
public static mesh Create_mesh(params triangle[] _t)
{
mesh m_ = new mesh();
m_.tris = _t.ToList();
return m_;
}
public static matrix4x4 Create_matrix4x4(params (int x, int y, float value)[] inputs)
{
matrix4x4 m_ = new matrix4x4();
m_.m = new float[4, 4];
foreach (var item in inputs)
{
m_.m[item.x, item.y] = item.value;
}
return m_;
}
public struct vector3d
{
public float x, y, z;
}
public struct triangle
{
public vector3d[] p;
}
public struct mesh
{
public List<triangle> tris;
}
public struct matrix4x4
{
public float[,] m;
};
}
}
}
I tried storing the cube with the calculated parameters, so I could draw it at once.
This was my only idea..
I am making a cubic voxel game. I have chunks, world, blocks and mesh generation done, but there's one problem - I could not do the texturing.
Everything I need is just add a texture to a side of a 3D mesh (Texture of every is different!). I've seen some implementations but it's hard to read somebody else's code (I've tried to use them, but it didn't work). I've tried to do this by myself, but with no results.
Can anybody explain how to do this??
Here is my current code:
[ExecuteInEditMode]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class Chunk : MonoBehaviour
{
private ushort[] _voxels = new ushort[16 * 16 * 16];
private MeshFilter meshFilter;
private Vector3[] cubeVertices = new[] {
new Vector3 (0, 0, 0),
new Vector3 (1, 0, 0),
new Vector3 (1, 1, 0),
new Vector3 (0, 1, 0),
new Vector3 (0, 1, 1),
new Vector3 (1, 1, 1),
new Vector3 (1, 0, 1),
new Vector3 (0, 0, 1),
};
private int[] cubeTriangles = new[] {
// Front
0, 2, 1,
0, 3, 2,
// Top
2, 3, 4,
2, 4, 5,
// Right
1, 2, 5,
1, 5, 6,
// Left
0, 7, 4,
0, 4, 3,
// Back
5, 4, 7,
5, 7, 6,
// Bottom
0, 6, 7,
0, 1, 6
};
public ushort this[int x, int y, int z]
{
get { return _voxels[x * 16 * 16 + y * 16 + z]; }
set { _voxels[x * 16 * 16 + y * 16 + z] = value; }
}
void Start()
{
meshFilter = GetComponent<MeshFilter>();
}
private void Update()
{
GenerateMesh();
}
public void GenerateMesh()
{
Mesh mesh = new Mesh();
List<Vector3> vertices = new List<Vector3>();
List<int> triangles = new List<int>();
for (var x = 0; x < 16; x++)
{
for (var y = 0; y < 16; y++)
{
for (var z = 0; z < 16; z++)
{
var voxelType = this[x, y, z];
if (voxelType == 0)
continue;
var pos = new Vector3(x, y, z);
var verticesPos = vertices.Count;
foreach (var vert in cubeVertices)
vertices.Add(pos + vert);
foreach (var tri in cubeTriangles)
triangles.Add(verticesPos + tri);
}
}
}
mesh.SetVertices(vertices);
mesh.SetTriangles(triangles.ToArray(), 0);
meshFilter.mesh = mesh;
}
}
NOTE: This is a repost with many edits so it is focused on one problem plus has better explanation. Sorry for that.
Like your SetVertices() and SetTriangles(), you can call a SetUVs() with a list of the UV coordinates of each vertex on your texture.
The UV list size must match the vertices list size!
The UV coordinate are expressed as Vector2 with values between 0 and 1.
For example, to apply the whole texture on the front face of your cube, you have the first 4 uvs like this:
private Vector2[] cubeUVs = new[] {
new Vector2 (0, 0),
new Vector2 (1, 0),
new Vector2 (1, 1),
new Vector2 (0, 1),
...
}
...
mesh.SetUVs(0, cubeUVs);
If your texture is not a square, then it will be stretched.
You should also call RecalculateBounds() and RecalculateNormals() at the end of your GenerateMesh() method to avoid some issues later.
EDIT
If you really want different texture files for each side of the cube, then the cleanest and most performant solution for me is to set a different VertexColor for each side of your cube, eg. (1,0,0), (0,1,0), (0,0,1), (1,1,0), (1,0,1) and (0,1,1).
However, you will have to duplicate all your vertices 3 times. (because the vertex color is bound to a vertex, and each vertex of a cube belongs to 3 sides)
(You still have to set the UVs like I said previously, but each side has the whole texture instead of only a part of the texture)
Then, you will have to create a custom shader with 6 textures in inputs (one for each side).
And in the fragment function, you select the right texture color according to the vertex color.
You can for that, do some if to select the texture, but it will be not very performant:
float3 finalColor;
if(vertexColor.r > 0.5f && vertexColor.g < 0.5f && vertexColor.b < 0.5f)
{
finalColor = text2D(_TopTexture, in.uv);
}
else if(...)
{
...
}
...
Or if you want more perf (with a lot of cubes), you can instead do some multiplications to select the right texture:
float3 topTexColor = text2D(_TopTexture, in.uv) * vertexColor.r * (1.0f - vertexColor.g) * (1.0f - vertexColor.b);
float3 frontTexColor = ...;
...
float3 finalColor = topTexColor + frontTexColor + ...;
Can anyone please help with the following?
Using Visual Studio 2019 Xamarin Forms project I am trying to display a rotating red square in the Android emulator. I have it working but my square is black:
Here's the code of my MainPage.xaml.cs (am using ES20 as ES10 does not have the OpenGL functions I need):
using OpenTK.Graphics.ES20;
using System;
using Xamarin.Forms;
namespace OGLMobile
{
public partial class MainPage : ContentPage
{
private float red = 1.0f;
private float green = 0.0f;
private float blue = 0.0f;
private const float halfWidth = 0.2f;
private float[] m_vertex_buffer_data = { 0.5f - halfWidth, 0.5f - halfWidth, 0.0f,
0.5f + halfWidth, 0.5f - halfWidth, 0.0f,
0.5f + halfWidth, 0.5f + halfWidth, 0.0f,
0.5f - halfWidth, 0.5f + halfWidth, 0.0f };
private string[] m_szVertexShader = null;
private string[] m_szFragmentShader = null;
private int m_nProgram = -1;
private int m_nVertexShaderHandle = -1;
private int m_nFragmentShaderHandle = -1;
private uint[] indices = { 0, 1, 2, 0, 2, 3 };
private int m_nVertexBuffer = -1;
bool m_bOGLParametersSet = false;
private void RotateSquare(float radians, float xRotationCentre, float yRotationCentre)
{
int[] nBaseIndices = { 0, 3, 6, 9 };
for (int nVertex = 0; nVertex <= 3 ; nVertex++)
{
int nIndex1 = nBaseIndices[nVertex];
int nIndex2 = nIndex1 + 1;
float offsetX = m_vertex_buffer_data[nIndex1] - xRotationCentre;
float offsetY = m_vertex_buffer_data[nIndex2] - yRotationCentre;
double xRotated = offsetX * Math.Cos(radians) - offsetY * Math.Sin(radians);
double yRotated = offsetX * Math.Sin(radians) + offsetY * Math.Cos(radians);
m_vertex_buffer_data[nIndex1] = (float)xRotated + xRotationCentre;
m_vertex_buffer_data[nIndex2] = (float)yRotated + yRotationCentre;
}
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, new IntPtr(m_vertex_buffer_data.Length * sizeof(float)), m_vertex_buffer_data);
}
public MainPage()
{
Title = "OpenGL";
var view = new OpenGLView { HasRenderLoop = true };
var toggle = new Switch { IsToggled = true };
m_szVertexShader = new string[1];
m_szFragmentShader = new string[1];
view.HeightRequest = 300;
view.WidthRequest = 300;
GL.Viewport(0, 0, 300, 300);
view.OnDisplay = r =>
{
if(!m_bOGLParametersSet) // Do this only on first rendering
{
CreateShader();
m_bOGLParametersSet = true;
GL.UseProgram(m_nProgram);
GL.GenBuffers(1, out m_nVertexBuffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(m_vertex_buffer_data.Length * sizeof(float)), m_vertex_buffer_data, BufferUsage.StaticDraw);
}
GL.ClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GL.Clear((ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));
RotateSquare(0.0174533f, 0.5f, 0.5f);
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.DrawElements(BeginMode.Triangles, indices.Length, DrawElementsType.UnsignedInt, indices);
GL.DisableVertexAttribArray(0);
};
toggle.Toggled += (s, a) =>
{
view.HasRenderLoop = toggle.IsToggled;
};
var stack = new StackLayout
{
Padding = new Size(20, 20),
Children = { view, toggle}
};
Content = stack;
}
private void SetShaderSource()
{
m_szVertexShader[0] = "void main()" +
"{" +
"gl_Position = ftransform();" +
"}";
m_szFragmentShader[0] = "void main()" +
"{" +
"gl_FragColor = vec4(1.0,0.0,0.0,1.0);" +
"}";
}
private void CreateShader()
{
SetShaderSource();
int nVertexShaderSourceLength = m_szVertexShader[0].Length;
int nFragmentShaderLength = m_szFragmentShader[0].Length;
m_nVertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
m_nFragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(m_nVertexShaderHandle, 1, m_szVertexShader, new int[] { nVertexShaderSourceLength });
GL.ShaderSource(m_nFragmentShaderHandle, 1, m_szFragmentShader, new int[] { nVertexShaderSourceLength });
GL.CompileShader(m_nVertexShaderHandle);
GL.CompileShader(m_nFragmentShaderHandle);
string szVertexShaderLog = GL.GetShaderInfoLog(m_nVertexShaderHandle);
string szFragmentShaderLog = GL.GetShaderInfoLog(m_nFragmentShaderHandle);
m_nProgram = GL.CreateProgram();
GL.AttachShader(m_nProgram, m_nVertexShaderHandle);
GL.AttachShader(m_nProgram, m_nFragmentShaderHandle);
GL.LinkProgram(m_nProgram);
}
}
}
My shaders must be incorrect, I get the same output if I replace them with junk strings, so the system must be defaulting to something.
I do have compile errors when I call GetShaderInfoLog, but my shaders are so trivial that I can't see the issue:
Thanks very much for any help, (been stuck on this for a while now. Have done plenty of OpenGL on desktop and with WebGL before, but not having any luck yet with mobile).
ADDITION: Thanks very much for you replies. I have replaced tha shaders with compliant ones, unfortunately I still have a black square:
(In the image it says mediump, I have also tried highp and lowp but I still get the same results).
I now get a different error on compilation of the vertex shader, and no error for the fragment shader - although I do have one warning for the latter:
Thank you for any further advice you may be able to offer.
These shaders do not meet any GLSL ES specification. See OpenGL ES Shading Language 1.00 Specification respectively. OpenGL ES Shading Language 3.00 Specification.
See a working shader with a vertex shader:
attribute vec3 a_position;
void main()
{
gl_Position = vec4(a_position, 1.0);
}
and fragment shader
precision mediump float;
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
I recommend to verify if the shader compiles with out errors:
GL.CompileShader(m_nVertexShaderHandle);
string infoLogFrag = GL.GetShaderInfoLog(m_nVertexShaderHandle);
if (infoLogFrag != System.String.Empty)
{
System.Console.WriteLine(infoLogFrag);
}
GL.CompileShader(m_nFragmentShaderHandle);
string infoLogVert = GL.GetShaderInfoLog(m_nFragmentShaderHandle);
if (infoLogVert != System.String.Empty)
{
System.Console.WriteLine(infoLogVert);
}
And the program links without errors:
GL.LinkProgram(m_nProgram);
string infoLogProg = GL.GetProgramInfoLog(m_nProgram );
if (infoLogProg != System.String.Empty)
{
System.Console.WriteLine(infoLogProg);
}
I have this function to convert Euler Angles to a rotation matrix but I would like to reverse it and get the Euler Angles when I only have the rotation matrix.
The reason for it is I want to be able to set an objects transform using a transform matrix then I would like to update that objects Euler rotation variable that is in degrees. (I have a function that calculate the rotation matrix from the transform matrix)
public static Mat4 RotMat(Vec3 _rot)
{
double rx = Math2.degToRad(_rot.x);
double[,] trmx = new double[4, 4] { { 1, 0, 0, 0 }, { 0, Math.Cos(rx), Math.Sin(rx), 0 }, { 0, -Math.Sin(rx), Math.Cos(rx), 0 }, { 0, 0, 0, 1 } };
Mat4 rmx = new Mat4(trmx);
double ry = Math2.degToRad(_rot.y);
double[,] trmy = new double[4, 4] { { Math.Cos(ry), 0, -Math.Sin(ry), 0 }, { 0, 1, 0, 0 }, { Math.Sin(ry), 0, Math.Cos(ry), 0 }, { 0, 0, 0, 1 } };
Mat4 rmy = new Mat4(trmy);
double rz = Math2.degToRad(_rot.z);
double[,] trmz = new double[4, 4] { { Math.Cos(rz), Math.Sin(rz), 0, 0 }, { -Math.Sin(rz), Math.Cos(rz), 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
Mat4 rmz = new Mat4(trmz);
return (rmx * rmy * rmz);
}
This is an attempt based on some code I found but does not always give me the expected result, it works sometimes (I know there is the gimbal lock issue with euler angles so maybe this is a futile attempt ).
public static Vec3 GetRot(Mat4 _tm)
{
Mat4 rm = GetRotMat(_tm);
double sy = Math.Sqrt(rm[0, 0] * rm[0, 0] + rm[1, 0] * rm[1, 0]);
bool singular = sy < 1e-6; // If
double x, y, z;
if (!singular)
{
x = Math.Atan2(rm[2, 1], rm[2, 2]);
y = Math.Atan2(-rm[2, 0], sy);
z = Math.Atan2(rm[1, 0], rm[0, 0]);
}
else
{
x = Math.Atan2(-rm[1, 2], rm[1, 1]);
y = Math.Atan2(-rm[2, 0], sy);
z = 0;
}
x = Math2.radToDeg(x);
y = Math2.radToDeg(y);
z = Math2.radToDeg(z);
return new Vec3(x, y, z) * -1;
}
I'm working on a Marching Cubes implementation in Unity. My code is based on Paul Bourke's code actually with a lot of modifications, but anyway i'm checking if a block at a position is null if it is than a debug texture will be placed on it.
This is my MC script
public class MarchingCubes
{
private World world;
private Chunk chunk;
private List<Vector3> vertices = new List<Vector3> ();
private List<Vector3> normals = new List<Vector3> ();
private Vector3[] ns;
private List<int> triangles = new List<int> ();
private List<Vector2> uvs = new List<Vector2> ();
private Vector3[] positions = new Vector3[8];
private float[] corners = new float[8];
private Vector3i size = new Vector3i (16, 128, 16);
Vector3[] vertlist = new Vector3[12];
private float isolevel = 1f;
private float Corner (Vector3i pos)
{
int x = pos.x;
int y = pos.y;
int z = pos.z;
if (x < size.x && z < size.z) {
return chunk.GetValue (x, y, z);
} else {
int ix = chunk.X, iz = chunk.Z;
int rx = chunk.region.x, rz = chunk.region.z;
if (x >= size.x) {
ix++;
x = 0;
}
if (z >= size.z) {
iz++;
z = 0;
}
return chunk.region.GetChunk (ix, iz).GetValue (x, y, z);
}
}
Block block;
public Mesh MarchChunk (World world, Chunk chunk, Mesh mesh)
{
this.world = world;
this.chunk = chunk;
vertices.Clear ();
triangles.Clear ();
uvs.Clear ();
for (int x = 0; x < size.x; x++) {
for (int y = 1; y < size.y - 2; y++) {
for (int z = 0; z < size.z; z++) {
block = chunk.GetBlock (x, y, z);
int cubeIndex = 0;
for (int i = 0; i < corners.Length; i++) {
corners [i] = Corner (new Vector3i (x, y, z) + offset [i]);
positions [i] = (new Vector3i (x, y, z) + offset [i]).ToVector3 ();
if (corners [i] < isolevel)
cubeIndex |= (1 << i);
}
if (eTable [cubeIndex] == 0)
continue;
for (int i = 0; i < vertlist.Length; i++) {
if ((eTable [cubeIndex] & 1 << i) == 1 << i)
vertlist [i] = LinearInt (positions [eCons [i, 0]], positions [eCons [i, 1]], corners [eCons [i, 0]], corners [eCons [i, 1]]);
}
for (int i = 0; triTable [cubeIndex, i] != -1; i += 3) {
int index = vertices.Count;
vertices.Add (vertlist [triTable [cubeIndex, i]]);
vertices.Add (vertlist [triTable [cubeIndex, i + 1]]);
vertices.Add (vertlist [triTable [cubeIndex, i + 2]]);
float tec = (0.125f);
Vector2 uvBase = block != null ? block.UV : new Vector2 ();
uvs.Add (uvBase);
uvs.Add (uvBase + new Vector2 (0, tec));
uvs.Add (uvBase + new Vector2 (tec, tec));
triangles.Add (index + 0);
triangles.Add (index + 1);
triangles.Add (index + 2);
}
}
}
}
if (mesh == null)
mesh = new Mesh ();
mesh.Clear ();
mesh.vertices = vertices.ToArray ();
mesh.triangles = triangles.ToArray ();
mesh.uv = uvs.ToArray ();
mesh.RecalculateNormals ();
return mesh;
}
bool IsBitSet (int b, int pos)
{
return ((b & pos) == pos);
}
Vector3 LinearInt (Vector3 p1, Vector3 p2, float v1, float v2)
{
Vector3 p;
p.x = p1.x + (isolevel - v1) * (p2.x - p1.x) / (v2 - v1);
p.y = p1.y + (isolevel - v1) * (p2.y - p1.y) / (v2 - v1);
p.z = p1.z + (isolevel - v1) * (p2.z - p1.z) / (v2 - v1);
return p;
}
private static int[,] eCons = new int[12, 2] {
{ 0, 1 },
{ 1, 2 },
{ 2, 3 },
{ 3, 0 },
{ 4, 5 },
{ 5, 6 },
{ 6, 7 },
{ 7, 4 },
{ 0, 4 },
{ 1, 5 },
{ 2, 6 },
{ 3, 7 }
};
private static Vector3i[] offset = new Vector3i[8] {
new Vector3i (0, 0, 1),
new Vector3i (1, 0, 1),
new Vector3i (1, 0, 0),
new Vector3i (0, 0, 0),
new Vector3i (0, 1, 1),
new Vector3i (1, 1, 1),
new Vector3i (1, 1, 0),
new Vector3i (0, 1, 0)
};
}
I didn't put the tables in the sample, because they are the same as the ones in Bourke's code.
EDIT:
What I figured out yet is that the cell's value at the blue triangles are 0 so they don't have to be triangulated, but the cell's value under them is 1 and because of this a top triangle is created to complete the mesh.