I integrated the code, I’m not done yet, but the vertex positions and normals is written out.
I had to stop when it came to the vertex indicies (running out of time tonight)
But I’ll continue tomorrow again after work.
By the way – I’m writing a offline renderer, not a ‘realtime’ renderer.
I’ve been working on the Luxrender project ( http://luxrender.net/ ) for many years,
I’ve been working on the 3dsmax exporter, for many years now I’ve maintained it and developed on it. The ‘old’ exporter exported to external files that you then rendered in the Luxrender standalone GUI.
This new renderer plugin I’m writing now is using the Luxcore library from the Luxrender project so that I can integrate the renderer directly in 3dsmax just like with mentalray, Iray, vray etc.
I knew there was a reason to include the index, it helps with the hash avoiding collisions (perfect boxes/exact mirrors can be troublesome) so…
static int hashPoint3(Point3& p) { return (*(int*)&p.x * 73856093)^(*(int*)&p.y * 19349663)^(*(int*)&p.z * 83492791); }
struct vertex : public MaxHeapOperators
{
static const int hashTable[];
Point3 p;
Point3 n;
Point3 uv;
int mid;
unsigned int index;
int hash;
vertex() : index(0), hash(0) {}
bool operator==(const vertex& v) const { return hash == v.hash; }
bool operator!=(const vertex& v) const { return hash != v.hash; }
bool operator>(const vertex& v) const { return hash > v.hash; }
bool operator<(const vertex& v) const { return hash < v.hash; }
void hashit()
{
hash ^= hashPoint3(p) * hashTable[0];
hash ^= hashPoint3(n) * hashTable[1];
hash ^= hashPoint3(uv) * hashTable[2];
hash ^= mid * hashTable[3];
hash ^= index * hashTable[4];
}
};
const int vertex::hashTable[] = { 93944371,36311839, 82895123, 10033109,59882063,42133979,24823181 };
and collect is like this…
vertexPtr CollectRawVerts(Mesh& mesh, int rawcount)
{
int numfaces = mesh.numFaces;
vertexPtr rawverts = new vertex[rawcount];
if(!rawverts) return NULL;
mesh.checkNormals(TRUE);
Face* faces = mesh.faces;
Point3* verts = mesh.verts;
TVFace* tvfaces = mesh.tvFace;
Point3* uvverts = mesh.tVerts;
for(int f = 0, i = 0; f < numfaces; ++f, ++faces, ++tvfaces)
{
Point3 fnormals[3];
GetFaceRNormals(mesh,f,fnormals);
short mid = faces->getMatID();
for(int v = 0; v < 3; ++v)
{
vertex& rv = rawverts[i++];
rv.index = faces->v[v];
rv.p = verts[faces->v[v]];
rv.n = fnormals[v];
rv.uv = uvverts[tvfaces->t[v]];
rv.mid = mid;
rv.hashit();
}
}
return rawverts;
}
Hi again, may I ask if you could explain how the vertex indicies works with this code?
I find it a bit confusing. (the other parts are fine)
they come as an array of ints first 3 are the face0, next 3 face1 etc upto numfaces * 3.
this shows how to build a max mesh from the vert and indices(faces)
void BuildMesh(Mesh& mesh, vertexPtr verts, int nverts, unsigned int* faces, int nfaces)
{
mesh.setNumVerts(nverts);
mesh.setNumFaces(nfaces);
mesh.setNumTVerts(nverts);
mesh.setNumTVFaces(nfaces);
MeshNormalSpec* nspec = new MeshNormalSpec;
nspec->SetNumFaces(nfaces);
nspec->SetNumNormals(nverts);
for(int v = 0; v < nverts; ++v)
{
mesh.setVert(v,verts[v].p);
mesh.setTVert(v,verts[v].uv);
nspec->Normal(v) = verts[v].n;
}
int fi = 0;
for(int f = 0; f < nfaces * 3; f += 3)
{
int a = faces[f];
int b = faces[f+1];
int c = faces[f+2];
mesh.faces[fi].setVerts(a,b,c);
mesh.tvFace[fi].setTVerts(a,b,c);
mesh.faces[fi].setEdgeVisFlags(1,1,1);
mesh.faces[fi].setMatID(verts[a].mid);
nspec->Face(fi).SetNormalID(0,a);
nspec->Face(fi).SetNormalID(1,b);
nspec->Face(fi).SetNormalID(2,c);
fi++;
}
nspec->MakeNormalsExplicit(false);
MeshNormalSpec *meshNormals = (MeshNormalSpec *)mesh.GetInterface(MESH_NORMAL_SPEC_INTERFACE);
if(meshNormals)
{
*meshNormals = *nspec;
meshNormals->SetParent(&mesh);
}
delete nspec;
}
Hm, I cannot seem to get it to work properly (probably my mistake),
I loop through, so the zero here is just a example for the first vert.
if i understand you correctly then that’s how it’s done?
vert 0 would be:
int vertIndex0 = rawverts[0].index;
vert 1 would be:
int vertIndex1 = rawverts[1].index;
… and so on?
I get some strange numbers back by doing it this way.
I’m trying to get the face indicies correct.
For each face I have to create a reference to each of the vertices at index X that face is built up from,
this tells the mesh that this face’s 3 verts is based on vertex X X X in vertexarray.
The code here:
for (int i = 0; i < (p_trimesh->getNumFaces()); i++)
{
Face* f = &p_trimesh->faces[i];
vi[i] = Triangle(f->v[0], f->v[1], f->v[2]);
mprintf(L"Writing face indicies face at Index %i = x:%i y:%i z:%i
", i, f->v[0], f->v[1], f->v[2]);
}
Creates this output (the vert point, and normal is from your code).
the indexes at the bottom is printed from the loop above here.
Info: Rawvert point x y z : -0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : -0.500000 , 0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 0.000000
Info: Rawvert point x y z : -0.500000 , 0.500000, 0.000000
Info: Rawvert point x y z : -0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : 0.500000 , 0.500000, 0.000000
Info: Rawvert point x y z : -0.500000 , 0.500000, 0.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 0.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , -0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , 0.500000, 1.000000
Info: Rawvert point x y z : -0.500000 , 0.500000, 0.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, -1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, -1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, -1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, -1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, -1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, -1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, 1.000000
Info: Rawvert normal x y z : 0.000000 , -0.000000, 1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, 1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, 1.000000
Info: Rawvert normal x y z : -0.000000 , 0.000000, 1.000000
Info: Rawvert normal x y z : 0.000000 , 0.000000, 1.000000
Info: Rawvert normal x y z : 0.000000 , -1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , -1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , -1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , -1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , -1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , -1.000000, 0.000000
Info: Rawvert normal x y z : 1.000000 , 0.000000, 0.000000
Info: Rawvert normal x y z : 1.000000 , 0.000000, -0.000000
Info: Rawvert normal x y z : 1.000000 , 0.000000, 0.000000
Info: Rawvert normal x y z : 1.000000 , 0.000000, 0.000000
Info: Rawvert normal x y z : 1.000000 , -0.000000, 0.000000
Info: Rawvert normal x y z : 1.000000 , 0.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , 1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , 1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , 1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , 1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , 1.000000, 0.000000
Info: Rawvert normal x y z : 0.000000 , 1.000000, 0.000000
Info: Rawvert normal x y z : -1.000000 , 0.000000, 0.000000
Info: Rawvert normal x y z : -1.000000 , 0.000000, 0.000000
Info: Rawvert normal x y z : -1.000000 , 0.000000, 0.000000
Info: Rawvert normal x y z : -1.000000 , 0.000000, 0.000000
Info: Rawvert normal x y z : -1.000000 , -0.000000, -0.000000
Info: Rawvert normal x y z : -1.000000 , 0.000000, 0.000000
Writing face indicies face at Index 0 = x:0 y:2 z:3
Writing face indicies face at Index 1 = x:3 y:1 z:0
Writing face indicies face at Index 2 = x:4 y:5 z:7
Writing face indicies face at Index 3 = x:7 y:6 z:4
Writing face indicies face at Index 4 = x:0 y:1 z:5
Writing face indicies face at Index 5 = x:5 y:4 z:0
Writing face indicies face at Index 6 = x:1 y:3 z:7
Writing face indicies face at Index 7 = x:7 y:5 z:1
Writing face indicies face at Index 8 = x:3 y:2 z:6
Writing face indicies face at Index 9 = x:6 y:7 z:3
Writing face indicies face at Index 10 = x:2 y:0 z:4
Writing face indicies face at Index 11 = x:4 y:6 z:2
The output it produces is a strange mesh:
http://bullet4max.com/owncloud/index.php/s/NfZgvVJ3v4jFlY6
this is the usage
int rawcount = mesh->numFaces * 3;
int optcount = 0;
vertexPtr rawverts = CollectRawVerts(*mesh, rawcount);
vertexPtr optverts = CreateOptimizeVertexList(rawverts, rawcount, optcount);
unsigned int* indices = CreateOptimizeFaceIndices(rawverts, rawcount, optverts, optcount);
optverts is the optimized vertex array and indices is the indexing into the that array to create the faces.
I misunderstood your code related to the indexes, so I asked a guy at work I know, he helped me out with some fixes for my end, so I’m going to test that as soon as I get home from work.
I think it’ll work now as it should, I’ll report back when it’s tested.