Trying to generate a sphere made of cubes like so:
This was easy, but any sphere of significant sizes has obvious performance issues if each cube is a separate gameobject, especially if the sphere is solid. After some digging, the answer appears to be to create a single mesh from only the exposed edges. Okay, makes sense. Found several videos, this one was the best I could find: link
I was able to customize the script for my needs, but I keep getting what appears to be a 2x2x2 cube regardless of the diameter input. I should be getting a hollow sphere made of a single mesh.
I suspect the issue is that I am not attaching the script to the correct type of gameobject, am missing a needed component on the gameobject, or because I skipped the UV portion.
Can anyone offer some advice?
Code:
public class PlanetGeneration : MonoBehaviour
{
private int planetDia = 30;
private int planetRadius;
//array of bools to keep track if each space is solid(true) or void(false)
private bool[,,] currentPlanet;
void Start()
{
currentPlanet = new bool[planetDia, planetDia, planetDia];
planetRadius = planetDia / 2 + 1;
GeneratePlanet();
GenerateMesh();
}
//define each block as void or solid
public void GeneratePlanet()
{
Vector3 planetCenter = new(planetRadius, planetRadius, planetRadius);
Vector3 currentPoint;
for (int x = 0; x < planetDia; x++)
{
for (int y = 0; y < planetDia; y++)
{
for (int z = 0; z < planetDia; z++)
{
//set the current position
currentPoint = new Vector3(x, y, z);
//check if this point is within the desired planet size
if (Vector3.Distance(planetCenter, currentPoint) <= planetRadius)
{
//make it a solid block
currentPlanet[x, y, z] = true;
}
//make it void
else currentPlanet[x, y, z] = false;
}
}
}
}
//generate mesh
public void GenerateMesh()
{
List<Vector3> Vertices = new List<Vector3>();
List<int> Triangles = new List<int>();
for (int x = 0; x < planetDia; x++)
{
for (int y = 0; y < planetDia; y++)
{
for (int z = 0; z < planetDia; z++)
{
//the 8 corners of a cube
Vector3[] VertexPos = new Vector3[8]
{
new Vector3(-1, 1, -1), new Vector3(-1, 1, 1),
new Vector3(1, 1, 1), new Vector3(1, 1, -1),
new Vector3(-1, -1, -1), new Vector3(-1, -1, 1),
new Vector3(1, -1, 1), new Vector3(1, -1, -1),
};
//first 4 digits are the vertices of the face, and the last 3 are the relative coords of the next block in that direction
int[,] Faces = new int[6, 7]{
{0, 1, 2, 3, 0, 1, 0}, //top
{7, 6, 5, 4, 0, -1, 0}, //bottom
{2, 1, 5, 6, 0, 0, 1}, //right
{0, 3, 7, 4, 0, 0, -1}, //left
{3, 2, 6, 7, 1, 0, 0}, //front
{1, 0, 4, 5, -1, 0, 0} //back
};
//if this block is solid
if (currentPlanet[x, y, z] == true)
{
//for each face of the block
for (int i = 0; i < 6; i++)
{
//check if it is on the edge of the overall array
//This part is dumb and needs to be removed. Keeping for now to prevent the array out of bounds error.
if(x + Faces[i, 4] == -1 || y + Faces[i, 5] == -1 || z + Faces[i, 6] == -1 ||
x + Faces[i, 4] == planetDia || y + Faces[i, 5] == planetDia || z + Faces[i, 6] == planetDia)
{
//do nothing
}
//check if the block next to it is void
else if(currentPlanet[x + Faces[i, 4], y + Faces[i, 5], z + Faces[i, 6]] == false)
{
AddQuad(Faces[i, 0], Faces[i, 1], Faces[i, 2], Faces[i, 3], Vertices.Count);
}
}
}
void AddQuad(int ai, int bi, int ci, int di, int i)
{
Vector3 a = VertexPos[ai];
Vector3 b = VertexPos[bi];
Vector3 c = VertexPos[ci];
Vector3 d = VertexPos[di];
Vertices.AddRange(new List<Vector3>() { a, b, c, d });
Triangles.AddRange(new List<int>() { i, i + 1, i + 2, i, i + 2, i + 3 });
}
}
}
}
this.gameObject.GetComponent<MeshFilter>().mesh = new Mesh()
{
vertices = Vertices.ToArray(),
triangles = Triangles.ToArray(),
};
}
}
After some more testing, and finding the youtube video authors updated code on github, I made several corrections and got it working. Code below in case anyone wants to reference.
Also of note - make a blank game object, attach the script, add a mesh filter and mesh renderer, set the material in the renderer.
This is a good starting point for anyone looking for this basic idea.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class PlanetGeneration : MonoBehaviour
{
//must be an odd number
private int planetDia = 39;
private int planetRadius;
//array of bools to keep track if each space is solid(true) or void(false)
private bool[,,] currentPlanet;
void Start()
{
currentPlanet = new bool[planetDia, planetDia, planetDia];
planetRadius = planetDia / 2 - 1;
GeneratePlanet();
GenerateMesh();
}
//define each block as void or solid
public void GeneratePlanet()
{
Vector3 planetCenter = new(planetRadius + 1, planetRadius + 1, planetRadius + 1);
Vector3 currentPoint;
for (int x = 0; x < planetDia; x++)
{
for (int y = 0; y < planetDia; y++)
{
for (int z = 0; z < planetDia; z++)
{
//set the current position
currentPoint = new Vector3(x, y, z);
//check if this point is within the desired planet size
if (Vector3.Distance(planetCenter, currentPoint) <= planetRadius)
{
//make it a solid block
currentPlanet[x, y, z] = true;
}
//make it void
else currentPlanet[x, y, z] = false;
}
}
}
}
//generate mesh
public void GenerateMesh()
{
List<int> Triangles = new();
List<Vector3> Verticies = new();
List<Vector2> uv = new();
for (int x = 1; x < planetDia; x++)
{
for (int y = 1; y < planetDia; y++)
{
for (int z = 1; z < planetDia; z++)
{
//the 8 corners of a cube
Vector3[] VertexPos = new Vector3[8]
{
new Vector3(-1, 1, -1), new Vector3(-1, 1, 1),
new Vector3(1, 1, 1), new Vector3(1, 1, -1),
new Vector3(-1, -1, -1), new Vector3(-1, -1, 1),
new Vector3(1, -1, 1), new Vector3(1, -1, -1),
};
//first 4 digits are the vertices of the face, and the last 3 are the relative coords of the next block in that direction, the last two are for the UV
int[,] Faces = new int[6, 9]{
{0, 1, 2, 3, 0, 1, 0, 0, 0}, //top
{7, 6, 5, 4, 0, -1, 0, 1, 0}, //bottom
{2, 1, 5, 6, 0, 0, 1, 1, 1}, //right
{0, 3, 7, 4, 0, 0, -1, 1, 1}, //left
{3, 2, 6, 7, 1, 0, 0, 1, 1}, //front
{1, 0, 4, 5, -1, 0, 0, 1, 1} //back
};
//if this block is solid
if (currentPlanet[x, y, z] == true)
{
//for each face of the block
for (int i = 0; i < 6; i++)
{
//check if the block next to it is void
if(currentPlanet[x + Faces[i, 4], y + Faces[i, 5], z + Faces[i, 6]] == false)
{
AddQuad(i, Verticies.Count);
}
}
}
void AddQuad(int facenum, int v)
{
// Add Mesh
for (int i = 0; i < 4; i++) Verticies.Add(new Vector3(x, y, z) + VertexPos[Faces[facenum, i]] / 2f);
Triangles.AddRange(new List<int>() { v, v + 1, v + 2, v, v + 2, v + 3 });
// Add uvs
Vector2 bottomleft = new Vector2(Faces[facenum, 7], Faces[facenum, 8]) / 2f;
uv.AddRange(new List<Vector2>() { bottomleft + new Vector2(0, 0.5f), bottomleft + new Vector2(0.5f, 0.5f), bottomleft + new Vector2(0.5f, 0), bottomleft });
}
}
}
}
GetComponent<MeshFilter>().mesh = new Mesh()
{
vertices = Verticies.ToArray(),
triangles = Triangles.ToArray(),
uv = uv.ToArray()
};
}
}
i'm working on method that create a delivery order pdf but recently i have been asked to add more columns in the array. As a result my array doesn't fit in Portrait size anymore so i'm trying to rotate my page in Landscape mode but i can't manage to make it work here is my code (some word have been modified/deleted for professional secret but it remain understandable. Thanks in advance
public static void CreateDocument(String to)
{
System.Collections.Generic.List<Produit> listPro = new System.Collections.Generic.List<Produit>(MainWindow.produits);
//listPro = ;
// Create a new PDF document
PdfSharp.Pdf.PdfDocument document = new PdfSharp.Pdf.PdfDocument();
document.Info.Title = "Bon de livraison n°"+MainWindow.numOrder;
int numpage = 1;
decimal maxPerPage = 25.00M;
Decimal numberPage = listPro.Count / maxPerPage;
Console.WriteLine("nbr : "+ listPro.Count+ "/ 25 = "+ numberPage);
numberPage = Math.Ceiling(numberPage);
String watermark = "NE PAS DIFFUSER";
while (1 == 1)
{
// Create an empty page
PdfSharp.Pdf.PdfPage page = document.AddPage();
page.Orientation = PageOrientation.Landscape;
page.Rotate = (page.Rotate - 90) % 360;
// Get an XGraphics object for drawing watermark
var gfx2 = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend);
XFont fontWater = new XFont("Verdana", 40, XFontStyle.Bold);
XSize size = gfx2.MeasureString(watermark, fontWater);
// Define a rotation transformation at the center of the page
gfx2.TranslateTransform(page.Width / 2, page.Height / 2);
gfx2.RotateTransform(-Math.Atan(page.Height / page.Width) * 180 / Math.PI);
gfx2.TranslateTransform(-page.Width / 2, -page.Height / 2);
// Create a string format
XStringFormat format = new XStringFormat();
format.Alignment = XStringAlignment.Near;
format.LineAlignment = XLineAlignment.Near;
// Create a dimmed red brush
XBrush brush = new XSolidBrush(XColor.FromArgb(128, 255, 0, 0));
// Draw the string
gfx2.DrawString(watermark, fontWater, brush,
new XPoint((page.Width - size.Width) / 2, (page.Height - size.Height) / 2),
format);
gfx2.Dispose();
// Get an XGraphics object for drawing the order
XGraphics gfx = XGraphics.FromPdfPage(page);
/*gfx.TranslateTransform(page.Width / 2, page.Height / 2);
gfx.RotateTransform(-Math.Atan(page.Height / page.Width) *180 / Math.PI);
gfx.TranslateTransform(-page.Width / 2, -page.Height / 2);*/
// Create a font
XFont font = new XFont("Verdana", 11, XFontStyle.Bold);
XFont fontRegular = new XFont("Verdana", 8, XFontStyle.Regular);
XFont fontMedium = new XFont("Verdana", 7, XFontStyle.Regular);
XFont fontLittle = new XFont("Verdana", 6, XFontStyle.Regular);
XFont fontRegularBold = new XFont("Verdana", 8, XFontStyle.Bold);
// Draw the text
gfx.DrawString("Bon de livraison", font, XBrushes.Black,
new XRect(0, 0, page.Width, 100),
XStringFormats.Center);
gfx.DrawString(to, font, XBrushes.Black,
new XRect(0, 0, page.Width, 130),
XStringFormats.Center);
gfx.DrawString("Produit à usage non thérapeutique", fontRegular, XBrushes.Black,
new XRect(0, 0, page.Width, 160),
XStringFormats.Center);
int x, y;
x = 40;
y = 80;
if (numpage == 1)
{
// gfx.DrawString(to, font, XBrushes.Black, page.Width, 100);
gfx.DrawString("Producteur : ", fontRegular, XBrushes.Black, x - 20, y - 50);
gfx.DrawString("", fontRegular, XBrushes.Black, x - 10, y - 40);
gfx.DrawString(" ", fontRegular, XBrushes.Black, x - 10, y - 30);
gfx.DrawString("", fontRegular, XBrushes.Black, x - 10, y - 20);
gfx.DrawString("N°BL", fontRegular, XBrushes.Black, x, y);
gfx.DrawLine(XPens.Black, x + 110, y - 10, x + 170, y - 10);
gfx.DrawLine(XPens.Black, x + 110, y + 4, x + 170, y + 4);
gfx.DrawLine(XPens.Black, x + 110, y - 10, x + 110, y + 4);
gfx.DrawLine(XPens.Black, x + 170, y - 10, x + 170, y + 4);
gfx.DrawString(MainWindow.numOrder.ToString(), fontRegular, XBrushes.Black, x + 113, y);
x = 700;
gfx.DrawString("to : ", fontRegular, XBrushes.Black, x - 30, y - 50);
gfx.DrawString("", fontRegular, XBrushes.Black, x - 20, y - 40);
gfx.DrawString("", fontRegular, XBrushes.Black, x - 20, y - 30);
gfx.DrawString("", fontRegular, XBrushes.Black, x - 20, y - 20);
gfx.DrawString("Technicien", fontRegular, XBrushes.Black, x - 20, y);
gfx.DrawLine(XPens.Black, x + 60, y - 10, x + 120, y - 10);
gfx.DrawLine(XPens.Black, x + 60, y + 4, x + 120, y + 4);
gfx.DrawLine(XPens.Black, x + 60, y - 10, x + 60, y + 4);
gfx.DrawLine(XPens.Black, x + 120, y - 10, x + 120, y + 4);
gfx.DrawString(MainWindow.intervenant, fontRegular, XBrushes.Black, x + 63, y);
x = 40;
y = y + 20;
gfx.DrawString("Date d'envoi des Produits", fontRegular, XBrushes.Black, x, y);
gfx.DrawLine(XPens.Black, x + 110, y - 10, x + 170, y - 10);
gfx.DrawLine(XPens.Black, x + 110, y + 4, x + 170, y + 4);
gfx.DrawLine(XPens.Black, x + 110, y - 10, x + 110, y + 4);
gfx.DrawLine(XPens.Black, x + 170, y - 10, x + 170, y + 4);
gfx.DrawString("10/03/2020", fontRegular, XBrushes.Black, x + 113, y);
x = 700;
gfx.DrawString("Nombre de produit", fontRegular, XBrushes.Black, x - 20, y);
gfx.DrawLine(XPens.Black, x + 60, y - 10, x + 120, y - 10);
gfx.DrawLine(XPens.Black, x + 60, y + 4, x + 120, y + 4);
gfx.DrawLine(XPens.Black, x + 60, y - 10, x + 60, y + 4);
gfx.DrawLine(XPens.Black, x + 120, y - 10, x + 120, y + 4);
gfx.DrawString(listPro.Count + "", fontRegular, XBrushes.Black, x + 63, y);
x = 40;
y = y + 20;
gfx.DrawString("Date d'envoi du BL", fontRegular, XBrushes.Black, x, y);
gfx.DrawLine(XPens.Black, x + 110, y - 10, x + 170, y - 10);
gfx.DrawLine(XPens.Black, x + 110, y + 4, x + 170, y + 4);
gfx.DrawLine(XPens.Black, x + 110, y - 10, x + 110, y + 4);
gfx.DrawLine(XPens.Black, x + 170, y - 10, x + 170, y + 4);
gfx.DrawString("10/03/2020", fontRegular, XBrushes.Black, x + 113, y);
}
else
{
y = 100;
}
x = 50;
y += 20;
int ydebut = y;
int xdebut = x;
if (to == "Yes")
{
gfx.DrawString("", fontRegular, XBrushes.Black, x -= 38, y + 12);
gfx.DrawString("Type", fontRegular, XBrushes.Black, x += 60, y + 12);
gfx.DrawString("N°Lymphobank", fontRegular, XBrushes.Black, x += 30, y + 12);
gfx.DrawString("Volume",fontRegular, XBrushes.Black, x+=40,y+12);
/*gfx.DrawString("IH et groupe sanguin", fontRegular, XBrushes.Black, x += 80, y + 12);
gfx.DrawString("Age", fontRegular, XBrushes.Black, x += 90, y + 12);
gfx.DrawString("Sexe", fontLittle, XBrushes.Black, x += 20, y + 12);
gfx.DrawString("Résultats Qualification Biologique du Don", fontRegular, XBrushes.Black, x += 20, y + 12);
gfx.DrawString("Blocage", fontLittle, XBrushes.Black, x += 370, y + 12);
gfx.DrawString("NbrDon", fontLittle, XBrushes.Black, x += 30, y + 12);
gfx.DrawString("Donneur Connu", fontRegular, XBrushes.Black, x += 30, y + 12);
*/// gfx.DrawLine(XPens.Black, xdebut - 40, y, x, y);
}
if (to != "YES")
{
gfx.DrawString("Numéro Lymphobank", fontMedium, XBrushes.Black, x += 3, y + 12);
gfx.DrawString("Volume (ml)", fontMedium, XBrushes.Black, x += 90, y + 12);
gfx.DrawString("IH et groupe sanguin", fontMedium, XBrushes.Black, x += 53, y + 12);
gfx.DrawString("Age", fontMedium, XBrushes.Black, x += 90, y + 12);
gfx.DrawString("Sexe", fontMedium, XBrushes.Black, x += 20, y + 12);
gfx.DrawString("Résultats Qualification Biologique du Don", fontMedium, XBrushes.Black, x += 25, y + 12);
gfx.DrawString("Blocage", fontMedium, XBrushes.Black, x += 370, y + 12);
gfx.DrawString("Nbr Don", fontMedium, XBrushes.Black, x += 40, y + 12);
gfx.DrawString("Donneur Connu", fontMedium, XBrushes.Black, x += 40, y + 12);
}
int Nproduit = 0;
foreach (Produit pro in listPro)
{
Nproduit++;
y += 15;
x = xdebut;
// NumeroYES = prod.GetYES()
//NumeroTypeProduit = prod.GetNumTypeYESProduit()
// Sexe = "" + prod.GetSexe() + "",
//DateNaissance = "" + prod.GetDateNaissance() + "",
if (to == "YES")
{
//gfx.DrawLine(XPens.Black, x -= 40, y + 3, xdebut, y + 3);
gfx.DrawString(pro.GetYES(), fontRegular, XBrushes.Black, x += 3, y + 12);
gfx.DrawString(pro.GetNumTypeYESProduit(), fontRegular, XBrushes.Black, x += 60, y + 12);
gfx.DrawString(pro.ToString(), fontRegular, XBrushes.Black, x += 30, y + 12);
gfx.DrawString(pro.GetVolume(), fontRegular, XBrushes.Black, x += 30, y + 12);
/* gfx.DrawString(pro.GetGroupeSimple(pro.GetGroupeProduit()) + pro.GetGroupeNonElargie(pro.GetGroupeProduit()), fontRegular, XBrushes.Black, x += 80, y + 12);
gfx.DrawString(pro.GetDateNaissance(), fontRegular, XBrushes.Black, x += 90, y + 12);
gfx.DrawString("" + pro.GetSexe() + "", fontRegular, XBrushes.Black, x += 20, y + 12);
gfx.DrawString(pro.GetResultatQBDTrans(), fontRegular, XBrushes.Black, x += 20, y + 12);
gfx.DrawString(pro.GetBlocage(), fontRegular, XBrushes.Black, x += 370, y + 12);
gfx.DrawString(pro.GetNombreDon(), fontRegular, XBrushes.Black, x += 30, y + 12);
gfx.DrawString(pro.GetDonneurConnu(), fontRegular, XBrushes.Black, x += 30, y + 12);
gfx.DrawLine(XPens.Black, xdebut, y + 3, x += 80 - 3, y + 3);*/
}
else
{
gfx.DrawString(pro.ToString(), fontMedium, XBrushes.Black, x += 3, y + 12);
gfx.DrawString(pro.GetVolume(), fontMedium, XBrushes.Black, x += 90, y + 12);
gfx.DrawString(pro.GetGroupeSimple(pro.GetGroupeProduit()) + pro.GetGroupeNonElargie(pro.GetGroupeProduit()), fontMedium, XBrushes.Black, x += 53, y + 12);
gfx.DrawString(pro.GetDateNaissance(), fontMedium, XBrushes.Black, x += 90, y + 12);
gfx.DrawString("" + pro.GetSexe() + "", fontMedium, XBrushes.Black, x += 20, y + 12);
gfx.DrawString(pro.GetResultatQBDTrans(), fontMedium, XBrushes.Black, x += 25, y + 12);
gfx.DrawString(pro.GetBlocage(), fontMedium, XBrushes.Black, x += 370, y + 12);
gfx.DrawString(pro.GetNombreDon(), fontMedium, XBrushes.Black, x += 40, y + 12);
gfx.DrawString(pro.GetDonneurConnu(), fontMedium, XBrushes.Black, x += 40, y + 12);
gfx.DrawLine(XPens.Black, xdebut, y + 3, x += 90 - 3, y + 3);
}
if (Nproduit == 25)
{
break;
}
}
listPro.RemoveRange(0, Nproduit);
y += 15;
x = xdebut;
if (to == "YES")
{
/*gfx.DrawLine(XPens.Black, x - 40, y + 3, x, y + 3);
gfx.DrawLine(XPens.Black, x -= 40, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 60, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 30, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 80, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 90, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 20, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 20, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 370, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 30, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 30, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 80, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, xdebut, y + 3, x, y + 3);
gfx.DrawLine(XPens.Black, xdebut - 40, ydebut, x, ydebut);*/
}
else
{
/* gfx.DrawLine(XPens.Black, x, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 90, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 90, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 20, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 25, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 370, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 40, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 40, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, x += 90, ydebut, x, y + 3);
gfx.DrawLine(XPens.Black, xdebut, y + 3, x, y + 3);
gfx.DrawLine(XPens.Black, xdebut, ydebut, x, ydebut);
*/
}
gfx.DrawString("Page "+numpage + "/" + numberPage, fontRegular, XBrushes.Black, 750, 580);
if (listPro.Count > 0)
{
Console.WriteLine("Nombre "+listPro.Count);
numpage++;
}
else
{
break;
}
}
// Save the document...
string filename = "BonDeLivraison_" + to+".pdf";
try
{
document.Save(filename);
Console.WriteLine("Fichier sauvegarder : "+filename);
//OUverture du document pur debug a enelever (mettre en commentaire)
//Process.Start(filename);
//decommenter pour que ca imprime automatiquement
RawPrinterHelper.SendFileToPrinter(MainWindow.imprimanteBon.getImprimanteText(),filename);
}
catch(Exception err)
{
MessageBox.Show(err+"", "Suppression du produit");
}
}
Hello
This is my function that will detect hit.
private int[] GetSelected(int x, int y)
{
const int max = 512;
var Hit_Buffer = new int[max];
var viewport = new int[4];
Gl.glSelectBuffer(max, Hit_Buffer);
Gl.glRenderMode(Gl.GL_SELECT);
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glPushMatrix();
Gl.glLoadIdentity();
Glu.gluLookAt(Distance * Math.Cos(beta) * Math.Cos(alpha)
, Distance * Math.Cos(beta) * Math.Sin(alpha)
, Distance * Math.Sin(beta)
, 0, 0, 0
, -Math.Sin(beta) * Math.Cos(alpha)
, -Math.Sin(beta) * Math.Sin(alpha)
, Math.Cos(beta));
Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);
Glu.gluPickMatrix(x, viewport[3] - y, 1, 1, viewport);
Glu.gluPerspective(fovY, ogl1.Width / (double)(ogl1.Height != 0 ? ogl1.Height : 1), 0.1, 100.0);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glInitNames();
// render scene: a TRIANGLE
Gl.glPushName(1);
Gl.glBegin(Gl.GL_TRIANGLES);
Gl.glVertex3d(0, 0, 0);
Gl.glVertex3d(0, 1, 0);
Gl.glVertex3d(1, 0, 0);
Gl.glEnd();
Gl.glPopName();
//
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glPopMatrix();
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glFlush();
var hits = Gl.glRenderMode(Gl.GL_RENDER);
Array.Resize(ref Hit_Buffer, hits);
return Hit_Buffer;
}
I am drawing a triangle in xy plane.
In gluLookAt, beta is camera angle from xy plane and alpha is camera angle about z.
But it just works if beta be small ( -15< beta <15 degree )!
What is wrong here?
In OpenGL Y is up
For the first 3 parameters, I'd rather say :
Distance * Math.Cos(beta) * Math.Cos(alpha)
, Distance * Math.Sin(beta)
, Distance * Math.Cos(beta) * Math.Sin(alpha)
And for the 3 last ones, try with (0,1,0) first.
Have you called gluLookAt before gluPickMatrix on purpose. Do you want to apply translations to your pick matrix? If not can you move gluPickMatrix immediately after glLoadIdentity and try if your problem gets resolved?
Hello again
I finally find my answer by myself! (by googling)
Here is my corrected code
private int[] GetSelected(int x, int y, bool debug)
{
var hits = 0; // number of hits
// Define select buffer
const int max = 512;
var Hit_buffer = new int[max];
Gl.glSelectBuffer(max, Hit_buffer);
var viewport = new int[4];
Gl.glViewport(0, 0, Width, (Height != 0 ? Height : 1));
Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);
if (debug)// show real scene in debug mode
GlDraw();
if(!debug)
Gl.glRenderMode(Gl.GL_SELECT);
int s = debug ? 60 : 3; // test region size
Gl.glLoadIdentity();
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glPushMatrix();
Gl.glLoadIdentity();
Glu.gluPickMatrix(x, viewport[3] - y, s, s, viewport);
Glu.gluPerspective(fovY, Width / (double)(Height != 0 ? Height : 1), 0.1, 1000.0);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
if (debug) // test region will be shown in left-bottom corner
Gl.glViewport(0, 0, s, s);
#region camera
Gl.glTranslated(Dx, Dy, 0);
var Distance = this.Distance;// *ogl1.Height / 60.0;
var CenterView = this.CenterView.Duplicate();
Glu.gluLookAt(Distance * Math.Cos(beta) * Math.Cos(alpha) + CenterView.x
, Distance * Math.Cos(beta) * Math.Sin(alpha) + CenterView.y
, Distance * Math.Sin(beta) + CenterView.z
, CenterView.x
, CenterView.y
, CenterView.z
, -Math.Sin(beta) * Math.Cos(alpha)
, -Math.Sin(beta) * Math.Sin(alpha)
, Math.Cos(beta));
#endregion
if (debug) // draw a bacground in left-bottom corner
{
ChangeColor(Color.Blue);
Glu.gluSphere(Glu.gluNewQuadric(), 50, 50, 50);
Gl.glBegin(Gl.GL_QUADS);
Gl.glVertex3d(-10, -10, -10);
Gl.glVertex3d(-10, 10, -10);
Gl.glVertex3d(10, 10, -10);
Gl.glVertex3d(10, -10, -10);
Gl.glEnd();
}
Gl.glInitNames();
// render scene
foreach (var b in Bodies)
{
Gl.glPushName(b.id);
var bb = b.Duplicate();
bb.color = Color.Red;
bb.Draw();
Gl.glPopName();
}
//
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glPopMatrix();
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glFlush();
if (!debug)
hits = Gl.glRenderMode(Gl.GL_RENDER);
// process hits
int[] Res = { };
int startRecord = 0;
for (int i = 0; i < hits; i++)
{
for (int j = 0; j < Hit_buffer[startRecord]; j++)
{
Array.Resize(ref Res, Res.Length + 1);
Res[Res.Length - 1] = Hit_buffer[startRecord + 3 + j];
}
startRecord += 3 + Hit_buffer[startRecord];
}
return Res;
}
If you set the debug parameter =true, it will draw the select region in left-bottom corner.
The code may be boring, so I am gonna write main parts here
// Define select buffer
const int max = 512;
var Hit_buffer = new int[max];
Gl.glSelectBuffer(max, Hit_buffer);
var viewport = new int[4];
Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);
Gl.glRenderMode(Gl.GL_SELECT);
Gl.glLoadIdentity();
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glPushMatrix();
Gl.glLoadIdentity();
Glu.gluPickMatrix(x, viewport[3] - y, 3, 3, viewport);
Glu.gluPerspective(fovY, Width / (double)(Height != 0 ? Height : 1), 0.1, 1000.0);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glInitNames();
// set camera (gluLookAt, ...) & draw scene
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glPopMatrix();
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glFlush();
var hits = Gl.glRenderMode(Gl.GL_RENDER);
// process hits