

各頂点に対して，
隣接する頂点の平均位置に向かって移動させることで多面体の形状を滑らかにしていくプログラムを完成させたいです。キーボードで's'を入力するごとに形状が滑らかになっていきます。  
しかし、's'を入力しても滑らかにはなりません。load_object内が間違っていると思われるのですが、改善点がわかりません。load_object内でどのようなことが行われており、隣接する頂点を格納していく方法を教えていただきたいです。

[code]

    #include <stdio.h>
    #include <stdlib.h>
    
    #if defined(__APPLE__) || defined(MACOSX)
    #include <GLUT/glut.h>
    #else
    #include <GL/glut.h>
    #endif
    
    #define WINDOW_SIZE      (512)
    #define MAX_VERTICES     (16384)
    #define MAX_EDGES        (16384)
    #define MAX_FACES        (16384)
    #define MAX_CORNERS      (64)
    #define MAX_ADJS     (32)
    
    #define LAMBDA          (0.6307)
    #define MU              (LAMBDA/(0.1*LAMBDA-1.0))
    #define NO_INDEX        (-1)
    
    static int width        = WINDOW_SIZE;
    static int height       = WINDOW_SIZE;
    
    #if defined(__APPLE__) || defined(MACOSX)
    int isRetina = 0;
    #endif
    typedef struct {
       double v[ 3 ];      // 3D coordinates
     int nAdjs;          // number of adjacent vertices
       int adj[ MAX_ADJS ];        // adjacent vertex IDs
    } coord;
    typedef struct {
       int vidO;           // origin vertex ID of the edge
       int vidD;           // destination vertex ID of the edge
       int fidL;           // left face ID
       int fidR;           // right face ID
    } winged;
    
    // structure for a face
    typedef struct {
       int vid[ MAX_CORNERS ];
                           // IDs of vertices on the face
                           // (Note that this data structure is
                           // redundant. Retaining a pointer to 
                           // an edge on the face is sufficient.
       int nV;             // number of vertices on the face
    } facet;
    
    // vertices
    int nVertices = 0;
    coord vertex[ MAX_VERTICES ];
    // edges
    int nEdges = 0;
    winged edge[ MAX_EDGES ];
    // faces
    int nFaces = 0;
    facet face[ MAX_FACES ];
    
    // angles of incidence and azimuth
    double incidence        = 45.0;
    double azimuth          = 30.0;
    // aspect ratio
    double aspect           =  1.0;
    // distance between the eye and origin
    double distance         =  6.0;
    
    // flags for mouse button ON/OFF (OFF = 0, ON = 1)
    int left_mouse = 0, middle_mouse = 0, right_mouse = 0;
    // previous coordinates of the mouse pointer
    int last_pointer_x, last_pointer_y;
    
    // search an existing edge
    static int search_edge( int orig, int dest )
    {
       int i;           // loop counter
    
       for ( i = 0; i < nEdges; i++ )
        if ( ( edge[ i ].vidO == orig ) && ( edge[ i ].vidD == dest ) )
            return i;
       // If the edge cannot be found, return NO_INDEX
       return NO_INDEX;
    }
    
    // load an object
    void load_object( char * filename )
    {
       int i, j, k;        // loop counters
       FILE * fp_r = NULL;  // file pointer
       char buf[ 256 ];     // temporary buffer
       int nCorners = 0;
       int corner[ MAX_CORNERS ];
                                   // array of corner vertex IDs
    
       // initialize the global variables
       nVertices = nEdges = nFaces = 0;
    
       // open the file
       if ( ( fp_r = fopen( filename, "r" ) ) == NULL ) {
           fprintf( stderr, "cannot open the file: %s\n", filename );
           return;
       }
    
       // load the number of vertices
       fgets( buf, sizeof( buf ), fp_r );
       sscanf( buf, "%d", &nVertices );
       fprintf( stderr, "Number of vertices = %d\n", nVertices );
       if ( nVertices > MAX_VERTICES ) {
           fprintf( stderr, "Too many vertices\n" );
           return;
       }
    
       // load coordinates of each vertex
       for ( i = 0; i < nVertices; i++ ) {
           fgets( buf, sizeof( buf ), fp_r );
           sscanf( buf, "%lf %lf %lf",
            &( vertex[ i ].v[ 0 ] ), &( vertex[ i ].v[ 1 ] ), &( vertex[ i ].v[ 2 ] ) );
        vertex[ i ].nAdjs = 0;
       }
    
       // load the number of faces
       fgets( buf, sizeof( buf ), fp_r );
       sscanf( buf, "%d", &nFaces );
       if ( nFaces > MAX_FACES ) {
           fprintf( stderr, "Too many faces\n" );
           nFaces = 0;
       }
    
       // load corner vertices of each face
       for ( i = 0; i < nFaces; i++ ) {
    
           // load the number of edges for each face
           fgets( buf, sizeof( buf ), fp_r );
           sscanf( buf, "%d", &nCorners );
           // load the corner vertex IDs of each face
           fgets( buf, sizeof( buf ), fp_r );
           k = 0;
           for ( j = 0; j < nCorners; j++ ) {
               while ( ( buf[ k ] == ' ' || buf[ k ] == '\t' ) ) k++;
               sscanf( &( buf[ k ] ), "%d", &( corner[ j ] ) );
               while ( ( '0' <= buf[ k ] ) && ( buf[ k ] <= '9' ) ) k++;
           }
    
           // generate winged-edge data elements
           for ( j = 0; j < nCorners; j++ ) {
               face[ i ].vid[ j ] = corner[ j ];
               int eidT = search_edge( corner[ (j+1)%nCorners ], corner[ j ] );
               // If the counter part does not exist, generate a new edge.
               if ( eidT == NO_INDEX ) {
                   int prevID, nextID;
                   prevID = corner[ j ];
                   nextID = corner[ (j+1)%nCorners ];
                   edge[ nEdges ].vidO = prevID;
                   edge[ nEdges ].vidD = nextID;
                   edge[ nEdges ].fidL = i;
                   nEdges++;
                   // For each vertex, register its adjacent vertices
        　
    
                
            
             }
               // Otherwise, the opposite face of an existing edge
               else {
                   edge[ eidT ].fidR = i;
               }
           }
        // generate a new face
        face[ i ].nV = nCorners;
       }
    
       fclose( fp_r );
    
       fprintf( stderr, "Number of edges = %d\n", nEdges );
       #ifdef DEBUG
       for ( i = 0; i < nEdges; ++i ) {
        fprintf( stderr,
             "Edge No. %3d is incident to Faces No. %3d and No. %3d\n",
             i, edge[ i ].fidL, edge[ i ].fidR );
       }
       #endif // DEBUG
       fprintf( stderr, "Number of faces = %d\n", nFaces );
       #ifdef DEBUG
       for ( i = 0; i < nFaces; ++i ) {
           fprintf( stderr, "Face No. %3d has Vertices ", i );
           for ( j = 0; j < face[ i ].nV; ++j ) {
               fprintf( stderr, "No. %3d", face[ i ].vid[ j ] );
               if ( j == face[ i ].nV - 2 ) fprintf( stderr, " and " );
               else if ( j == face[ i ].nV - 1 ) fprintf( stderr, "." );
               else fprintf( stderr, ", " );
           }
           fprintf( stderr, "\n" );
       }
       #endif // DEBUG
    }
    void weighted_average( double weight )
    {
       // temporary storage for coordinates
       static coord newcoord[ MAX_VERTICES ];
       // loop counters
       int i, j, k;
    
       // for each vertex
       for ( i = 0; i < nVertices; ++i ) {
           // average color of neighboring faces
           coord ave;
           // for each neighboring faces
           for ( k = 0; k < 3; ++k ) ave.v[ k ] = 0.0;
    
           // for each adjacent vertex
           for ( j = 0; j < vertex[ i ].nAdjs; ++j ) {
               int idAdj = vertex[ i ].adj[ j ];
               for ( k = 0; k < 3; ++k )
                   ave.v[ k ] += vertex[ idAdj ].v[ k ];
           }
           for ( k = 0; k < 3; ++k )
               ave.v[ k ] /= ( double )vertex[ i ].nAdjs;
    
           for ( k = 0; k < 3; ++k )
               newcoord[ i ].v[ k ] =
                   ( 1.0 - weight ) * vertex[ i ].v[ k ] + weight * ave.v[ k ];
       }
    
       // copy back the new coordinates
       for ( i = 0; i < nVertices; ++i ) {
           for ( k = 0; k < 3; ++k )
               vertex[ i ].v[ k ] = newcoord[ i ].v[ k ];
       }
    }
    
    void update_position( void )
    {
       weighted_average( LAMBDA );
       weighted_average( MU );
    }
    
    // draw the object 
    void draw_object( void )
    {
       // loop counters
       int i, j;
    
       // set the line width
       glLineWidth( 1.0 );
    // draw a list of edges
       // set the color of the edges
       glColor3d( 1.0, 1.0, 1.0 );
       // set rasterization type and polygon facing
       glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
       // for each face
       for ( i = 0; i < nFaces; ++i ) {
           // outline the face
        glBegin( GL_POLYGON );
        // for each corner vertex
        for ( j = 0; j < face[ i ].nV; ++j ) {
            glVertex3dv( vertex[ face[ i ].vid[ j ] ].v );
        }
        glEnd();
       }
    
       // hide the invisible lines by filling the face with the background color
       // set the color of the face
       glColor3d( 0.0, 0.0, 0.0 );
       // set rasterization type and polygon facing
       glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
       // enable polygon offset to avoid conflict with the polygon outlines
       glEnable( GL_POLYGON_OFFSET_FILL );
       glPolygonOffset( 1.0, 2.0 );
       // for each face
       for ( i = 0; i < nFaces; ++i ) {
           // fill the face
        glBegin( GL_POLYGON );
        // for each corner vertex
        for ( j = 0; j < face[ i ].nV; ++j ) {
            glVertex3dv( vertex[ face[ i ].vid[ j ] ].v );
        }
        glEnd();
       }
       glDisable( GL_POLYGON_OFFSET_FILL );
    
    }
    void display( void )
    {
       glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
       glMatrixMode( GL_MODELVIEW );
       glLoadIdentity();
       glTranslated( 0.0, 0.0, -distance );
       glRotated( -incidence, 1.0, 0.0, 0.0 );
       glRotated( -azimuth, 0.0, 0.0, 1.0 );
       draw_object();
       glutSwapBuffers();
    }
    void reshape( int w, int h )
    {
       width = w;
       height = h;
    #if defined(__APPLE__) || defined(MACOSX)
       if ( isRetina ) {
        width = w*2;
        height = h*2;
       }
    #endif
       glViewport ( 0, 0, width, height ); 
       glMatrixMode( GL_PROJECTION );
       glLoadIdentity ();
       aspect = ( double )w/( double )h;
       gluPerspective( 65.0, aspect, 0.1, 100.0 );
    }
    void keyboard( unsigned char key, int x, int y )
    {
      switch ( key ) {
        case 'q':
        case 'Q':
        case '\033':  // ASCII code of ESC
            exit( 0 );
            break;
        case '8':
            load_object( "horse.dat" );
            break;
        case 's':
            update_position();
            break;
        default:
            break;
      }
      glutPostRedisplay();
    }
    void init( void )
    {
    #if defined(__APPLE__) || defined(MACOSX)
       int originalViewport[ 4 ];
       glGetIntegerv( GL_VIEWPORT, originalViewport );
       if ( ( originalViewport[ 2 ] == WINDOW_SIZE * 2 ) &&
         ( originalViewport[ 3 ] == WINDOW_SIZE * 2 ) ) {
        fprintf( stderr, " Retina display!!\n" );
        isRetina = 1;
       }
       else {
        fprintf( stderr, " NOT Retina display!!\n" );
        isRetina = 0;
       }
    #endif
       glClearColor( 0.0, 0.0, 0.0, 0.0 );
       glEnable( GL_DEPTH_TEST );
       glEnable( GL_CULL_FACE );
       glCullFace( GL_BACK );
    }
    
    // main function
    int main( int argc, char *argv[] )
    {
       glutInit( &argc, argv );
       glutInitWindowPosition( 50, 50 );
       glutInitWindowSize( WINDOW_SIZE, WINDOW_SIZE );
       glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
       glutCreateWindow( argv[0] );
       glutDisplayFunc( display );
       glutReshapeFunc( reshape );
       glutKeyboardFunc( keyboard );
       init();
       glutMainLoop();
    
       return 0;
    }
    
[/code]


CC BY-SA 4.0
2022-07-11T14:07:18.757
89918
2022-07-12T08:56:26.947
2022-07-12T08:56:26.947
53466
53466
question
c++ c opengl
OpenGLを使ったコンピュータグラフィック