POV-Ray : Newsgroups : povray.programming : Mesh code : Mesh code Server Time
8 Jul 2024 18:57:47 EDT (-0400)
  Mesh code  
From: Christopher James Huff
Date: 22 Dec 2002 11:54:20
Message: <chrishuff-E75E92.11491822122002@netplex.aussie.org>
I've been working on a tessellation patch, and I'm having some rather 
bizzare problems. I've created a singleton class to make mesh creation 
easier, and I think the problem is in there, I assume I'm somehow not 
using the mesh code properly...the class is below. For some reason, a 
triangle sometimes gets a vertex from a different triangle, apparently 
the previous one. When I make quads from two triangles with vertices 
arranged like this:

D-C
|/|
A-B

The effect is as if the ABC triangle goes DBC, overlapping and leaving a 
gap. But it only does this sometimes: on one half of a cylinder, or 
specific segments of a tessellated sphere, even though the exact same 
code is creating the triangles.

/*
 *  meshfactory.h
 *  POV35
 *
 *  Created by Christopher James Huff on Fri Dec 20 2002.
 *  Copyright (c) 2002 Christopher James Huff. All rights reserved.
 *
 */

/*A very simple class created to assist in managing mesh creation,
a separate interface to the mesh code.*/

#ifndef MESH_FACTORY
#define MESH_FACTORY

#include "frame.h"
#include "mesh.h"

class MeshFactory {
  private:
    static MESH * mesh;
    
    static bool fullyTextured;
    
    static int numTriangles;
    static int numVertices;
    static int numNormals;
    static int numTextures;
    static int numUVCoords;
    
    static int maxTriangles;
    static int maxVertices;
    static int maxNormals;
    static int maxTextures;
    static int maxUVCoords;
    
    static MESH_TRIANGLE * triangles;
    static SNGL_VECT * vertices;
    static SNGL_VECT * normals;
    static TEXTURE ** textures;
    static UV_VECT * UVCoords;
    
    MeshFactory() {}//keep MeshFactory instances from being created
    ~MeshFactory() {}
  public:
    static void StartMesh();
    
    static void SetInsideVector(VECTOR ins);
    static void AddTriangle(VECTOR ptA, VECTOR ptB, VECTOR ptC, TEXTURE 
* t1 = NULL, TEXTURE * t2 = NULL, TEXTURE * t3 = NULL);
    static void AddTriangle(VECTOR ptA, VECTOR ptB, VECTOR ptC, VECTOR 
normA, VECTOR normB, VECTOR normC, TEXTURE * t1 = NULL, TEXTURE * t2 = 
NULL, TEXTURE * t3 = NULL);
    
    static void AddQuad(VECTOR p1, VECTOR p2, VECTOR p3, VECTOR p4, 
TEXTURE * t1 = NULL, TEXTURE * t2 = NULL, TEXTURE * t3 = NULL, TEXTURE * 
t4 = NULL);
    static void AddQuad(VECTOR p1, VECTOR p2, VECTOR p3, VECTOR p4, 
VECTOR n1, VECTOR n2, VECTOR n3, VECTOR n4, TEXTURE * t1 = NULL, TEXTURE 
* t2 = NULL, TEXTURE * t3 = NULL, TEXTURE * t4 = NULL);
    
    static MESH * GetMesh();
};

#endif


/*
 *  meshfactory.cpp
 *  POV35
 *
 *  Created by Christopher James Huff on Fri Dec 20 2002.
 *  Copyright (c) 2002 Christopher James Huff. All rights reserved.
 *
 */

#include "frame.h"
#include "pov_mem.h"
#include "povproto.h"
#include "vector.h"
#include "objects.h"
#include "texture.h"
#include "meshfactory.h"

#include <iostream>

MESH * MeshFactory::mesh = NULL;
bool MeshFactory::fullyTextured;
int MeshFactory::numTriangles;
int MeshFactory::numVertices;
int MeshFactory::numNormals;
int MeshFactory::numTextures;
int MeshFactory::numUVCoords;

int MeshFactory::maxTriangles;
int MeshFactory::maxVertices;
int MeshFactory::maxNormals;
int MeshFactory::maxTextures;
int MeshFactory::maxUVCoords;

MESH_TRIANGLE * MeshFactory::triangles;
SNGL_VECT * MeshFactory::vertices;
SNGL_VECT * MeshFactory::normals;
TEXTURE ** MeshFactory::textures;
UV_VECT * MeshFactory::UVCoords;

void MeshFactory::StartMesh()
{
    //need to check for non-NULL
    mesh = Create_Mesh();
    
    fullyTextured = true;
    mesh->has_inside_vector = false;
    
    maxTriangles = 256;
    maxVertices = 256;
    maxNormals = 256;
    maxTextures = 16;
    maxUVCoords = 256;
    
    numTriangles = 0;
    numVertices = 0;
    numNormals = 0;
    numTextures = 0;
    numUVCoords = 0;
    
    triangles = (MESH_TRIANGLE 
*)POV_MALLOC(maxTriangles*sizeof(MESH_TRIANGLE), "temporary triangle 
mesh data");
    vertices = (SNGL_VECT *)POV_MALLOC(maxVertices*sizeof(SNGL_VECT), 
"temporary triangle mesh data");
    normals = (SNGL_VECT *)POV_MALLOC(maxNormals*sizeof(SNGL_VECT), 
"temporary triangle mesh data");
    textures = (TEXTURE **)POV_MALLOC(maxTextures*sizeof(TEXTURE *), 
"temporary triangle mesh data");
    UVCoords = (UV_VECT *)POV_MALLOC(maxUVCoords*sizeof(UV_VECT), 
"temporary triangle mesh data");
    
    Create_Mesh_Hash_Tables();
}

void MeshFactory::SetInsideVector(VECTOR ins)
{
    VNormalize(mesh->Data->Inside_Vect, ins);
    mesh->has_inside_vector = true;
}


//could simplify by abstracting triangle
void MeshFactory::AddTriangle(VECTOR ptA, VECTOR ptB, VECTOR ptC, 
TEXTURE * t1, TEXTURE * t2, TEXTURE * t3)
{
    if(!Mesh_Degenerate(ptA, ptB, ptC))
    {
        if(numTriangles >= maxTriangles)
        {
            if(maxTriangles >= INT_MAX/2)
                Error("Too many triangles in triangle mesh.");
            
            maxTriangles *= 2;
            triangles = (MESH_TRIANGLE *)POV_REALLOC(triangles, 
maxTriangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
        }
        
        Init_Mesh_Triangle(&triangles[numTriangles]);
        
        triangles[numTriangles].P1 = Mesh_Hash_Vertex(&numVertices, 
&maxVertices, &vertices, ptA);
        triangles[numTriangles].P2 = Mesh_Hash_Vertex(&numVertices, 
&maxVertices, &vertices, ptB);
        triangles[numTriangles].P3 = Mesh_Hash_Vertex(&numVertices, 
&maxVertices, &vertices, ptC);
        
        triangles[numTriangles].Texture = 
Mesh_Hash_Texture(&numTextures, &maxTextures, &textures, t1);
        if(t2)
            triangles[numTriangles].Texture2 = 
Mesh_Hash_Texture(&numTextures, &maxTextures, &textures, t2);
        if(t3)
            triangles[numTriangles].Texture3 = 
Mesh_Hash_Texture(&numTextures, &maxTextures, &textures, t3);
        
        if(t2 || t3)
            triangles[numTriangles].ThreeTex = true;
        
        //Hash in UV coords, even though they aren't used.
        UV_VECT UV_Temp;
        triangles[numTriangles].UV1 = Mesh_Hash_UV(&numUVCoords, 
&maxUVCoords, &UVCoords, UV_Temp);
        triangles[numTriangles].UV2 = Mesh_Hash_UV(&numUVCoords, 
&maxUVCoords, &UVCoords, UV_Temp);
        triangles[numTriangles].UV3 = Mesh_Hash_UV(&numUVCoords, 
&maxUVCoords, &UVCoords, UV_Temp);
        
        
        VECTOR N;
        Compute_Mesh_Triangle(&triangles[numTriangles], false, ptA, ptB, 
ptC, N);

        triangles[numTriangles].Normal_Ind = 
Mesh_Hash_Normal(&numNormals, &maxNormals, &normals, N);
        
        if(triangles[numTriangles].Texture < 0)
            fullyTextured = false;

        numTriangles++;
    }
    else
    {
        Error("MeshFactory: Degenerate triangle.");
    }
}


//smooth triangle without UV
void MeshFactory::AddTriangle(VECTOR ptA, VECTOR ptB, VECTOR ptC, VECTOR 
normA, VECTOR normB, VECTOR normC, TEXTURE * t1, TEXTURE * t2, TEXTURE * 
t3)
{
    if(!Mesh_Degenerate(ptA, ptB, ptC))
    {
        if(numTriangles >= maxTriangles)
        {
            if(maxTriangles >= INT_MAX/2)
                Error("MeshFactory: Too many triangles in triangle 
mesh.");
            
            maxTriangles *= 2;
            triangles = (MESH_TRIANGLE *)POV_REALLOC(triangles, 
maxTriangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
        }
        
        Init_Mesh_Triangle(&triangles[numTriangles]);
        triangles[numTriangles].P1 = Mesh_Hash_Vertex(&numVertices, 
&maxVertices, &vertices, ptA);
        triangles[numTriangles].P2 = Mesh_Hash_Vertex(&numVertices, 
&maxVertices, &vertices, ptB);
        triangles[numTriangles].P3 = Mesh_Hash_Vertex(&numVertices, 
&maxVertices, &vertices, ptC);
        
        triangles[numTriangles].Texture = 
Mesh_Hash_Texture(&numTextures, &maxTextures, &textures, t1);
        if(t2)
            triangles[numTriangles].Texture2 = 
Mesh_Hash_Texture(&numTextures, &maxTextures, &textures, t2);
        if(t3)
            triangles[numTriangles].Texture3 = 
Mesh_Hash_Texture(&numTextures, &maxTextures, &textures, t3);
        
        if(t2 || t3)
            triangles[numTriangles].ThreeTex = true;
        
        //Hash in UV coords, even though they aren't used.
        UV_VECT UV_Temp;
        triangles[numTriangles].UV1 = Mesh_Hash_UV(&numUVCoords, 
&maxUVCoords, &UVCoords, UV_Temp);
        triangles[numTriangles].UV2 = Mesh_Hash_UV(&numUVCoords, 
&maxUVCoords, &UVCoords, UV_Temp);
        triangles[numTriangles].UV3 = Mesh_Hash_UV(&numUVCoords, 
&maxUVCoords, &UVCoords, UV_Temp);
        
        triangles[numTriangles].N1 = Mesh_Hash_Normal(&numNormals, 
&maxNormals, &normals, normA);
        triangles[numTriangles].N2 = Mesh_Hash_Normal(&numNormals, 
&maxNormals, &normals, normB);
        triangles[numTriangles].N3 = Mesh_Hash_Normal(&numNormals, 
&maxNormals, &normals, normC);
        
        //doesn't do as much checking as Parse_Mesh()
        VECTOR N;
        Compute_Mesh_Triangle(&triangles[numTriangles], true, ptA, ptB, 
ptC, N);

        triangles[numTriangles].Normal_Ind = 
Mesh_Hash_Normal(&numNormals, &maxNormals, &normals, N);
        
        if(triangles[numTriangles].Texture < 0)
            fullyTextured = false;

        numTriangles++;
    }
}

void MeshFactory::AddQuad(VECTOR p1, VECTOR p2, VECTOR p3, VECTOR p4,
                          TEXTURE * t1, TEXTURE * t2, TEXTURE * t3, 
TEXTURE * t4)
{
    //points:
    //4 3
    //1 2
    //Should find the longest axis and split across that
    AddTriangle(p1, p2, p3, t1, t2, t3);
    AddTriangle(p1, p3, p4, t1, t3, t4);
}

void MeshFactory::AddQuad(VECTOR p1, VECTOR p2, VECTOR p3, VECTOR p4,
                          VECTOR n1, VECTOR n2, VECTOR n3, VECTOR n4,
                          TEXTURE * t1, TEXTURE * t2, TEXTURE * t3, 
TEXTURE * t4)
{
    AddTriangle(p1, p2, p3, n1, n2, n3, t1, t2, t3);
    AddTriangle(p1, p3, p4, n1, n3, n4, t1, t3, t4);
}



MESH * MeshFactory::GetMesh()
{
    Destroy_Mesh_Hash_Tables();
    
    if(numTriangles == 0)
        Error("MeshFactory: No triangles in triangle mesh.");
    
    std::cout << "\nMeshFactory: mesh complete.\n"
              << "triangles: " << numTriangles
              << "\nvertices: " << numVertices
              << "\nnormals: " << numNormals << std::endl;
    
    mesh->Data = (MESH_DATA *)POV_MALLOC(sizeof(MESH_DATA), "triangle 
mesh data");
    mesh->Data->References = 1;
    mesh->Data->Tree = NULL;
    
    if(fullyTextured)
        mesh->Type |= TEXTURED_OBJECT;
    
    mesh->Data->Triangles = (MESH_TRIANGLE 
*)POV_MALLOC(numTriangles*sizeof(MESH_TRIANGLE), "triangle mesh data");
    mesh->Data->Number_Of_Triangles = numTriangles;
    mesh->Data->Vertices = (SNGL_VECT 
*)POV_MALLOC(numVertices*sizeof(SNGL_VECT), "triangle mesh data");
    mesh->Data->Number_Of_Vertices = numVertices;
    mesh->Data->Normals = (SNGL_VECT 
*)POV_MALLOC(numNormals*sizeof(SNGL_VECT), "triangle mesh data");
    mesh->Data->Number_Of_Normals = numNormals;
    mesh->Data->UVCoords = (UV_VECT 
*)POV_MALLOC(numUVCoords*sizeof(UV_VECT), "triangle mesh data");
    mesh->Data->Number_Of_UVCoords = numUVCoords;
    
    if(numTextures == 0)
    {
        mesh->Textures = NULL;
    }
    else
    {
        Set_Flag(mesh, MULTITEXTURE_FLAG);
        mesh->Textures = (TEXTURE 
**)POV_MALLOC(numTextures*sizeof(TEXTURE *), "triangle mesh data");
    }
    mesh->Number_Of_Textures = numTextures;
    
    for(int i = 0; i < numTriangles; i++)
        mesh->Data->Triangles[i] = triangles[i];
    
    for(int i = 0; i < numVertices; i++)
        Assign_SNGL_Vect(mesh->Data->Vertices[i], vertices[i]);
    
    for(int i = 0; i < numNormals; i++)
        Assign_SNGL_Vect(mesh->Data->Normals[i], normals[i]);
    
    for(int i = 0; i < numUVCoords; i++)
        Assign_UV_Vect(mesh->Data->UVCoords[i], UVCoords[i]);
    
    for (int i = 0; i < numTextures; i++)
    {
        mesh->Textures[i] = Copy_Textures(textures[i]);
        Post_Textures(mesh->Textures[i]);
        // now free the texture, in order to decrement the reference 
count
        Destroy_Textures(textures[i]);
        //Is all the above really necessary?
    }
    
    POV_FREE(triangles);
    POV_FREE(vertices);
    POV_FREE(normals);
    POV_FREE(textures);
    POV_FREE(UVCoords);
    
    Compute_Mesh_BBox(mesh);
    Build_Mesh_BBox_Tree(mesh);
    
    MESH * msh = mesh;
    mesh = NULL;
    return msh;
}

-- 
Christopher James Huff <cja### [at] earthlinknet>
http://home.earthlink.net/~cjameshuff/
POV-Ray TAG: chr### [at] tagpovrayorg
http://tag.povray.org/


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.