必要なときにコピペするためのもの.



描画関数

グリッド描画

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56

static int DrawGroundGrid(int d, double x, double y, double h)
{
 
    glPushMatrix();
    
    glDisable(GL_LIGHTING);
 
    glColor3f(1,0,0);
    glLineWidth(6.0);
    glBegin(GL_LINE_LOOP);
    glVertex3d(-x,  y, h);
    glVertex3d( x,  y, h);  
    glVertex3d( x, -y, h);
    glVertex3d(-x, -y, h);
    glEnd();
    glLineWidth(3.0);
    
        float x0, x1, y0, y1;
    float deltaX, deltaY;
 
    x0 = -x; x1 = -x;
    y0 = -y; y1 = y;
    deltaX = (2*x)/d;
 
    for(int i = 0; i < d; ++i){
        x0 = x0 + deltaX;
        glBegin(GL_LINES);
        glVertex3f(x0, y0, h);
        glVertex3f(x0, y1, h);
        glEnd();
    }
 
        x0 = -x; x1 = x;
    deltaY = (2*y)/d;
 
    for(int i = 0; i < d; ++i){
        y0 = y0 + deltaY;
        glBegin(GL_LINES);
        glVertex3f(x0, y0, h);
        glVertex3f(x1, y0, h);
        glEnd();
    }
 
    glLineWidth(1.0);
    glPopMatrix();
 
    return 0;
}

ポリゴン描画

rxMaterialは下の材質クラスを参照.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90

inline void DrawPolygon(const vector<Vec3> &verts, const vector<int> &index, const Vec3 &color)
{
    glBegin(GL_POLYGON);
    glColor3f(color[0], color[1], color[2]);
    for(int i = 0; i < (int)index.size(); ++i){
        glVertex3dv(verts[index[i]-1].data);
    }
    glEnd();
}
 
 

inline void DrawPolygonGouraud(const vector<Vec3> &verts, const vector<int> &index, 
                               const vector<Vec3> &norms, const Vec3 &color)
{
    Vec3 norm;
    Vec3 vert;
 
    glColor3f(color[0], color[1], color[2]);
 
    glBegin(GL_POLYGON);
    for(int i = 0; i < (int)index.size(); ++i){
        glNormal3dv(norms[index[i]-1].data);
        glVertex3dv(verts[index[i]-1].data);
    }
    glEnd();
}
 
 

static void DrawPolygons(const vector<Vec3> &vrts, const vector< vector<int> > &idxs, 
                         rxMaterial *gmat, bool select)
{
    int i;
    rxMaterial *mat;
    for(i = 0; i < (int)idxs.size(); ++i){
        if(gmat == NULL){
            mat = &g_matDefault;
        }
        else{
            mat = gmat;
        }
        
        if(select) glLoadName(i);
        mat->SetGL();
        glEnable(GL_LIGHTING);
        DrawPolygon(vrts, idxs[i], mat->GetDiff3());
    }
}
 

static void DrawPolygonsGouraud(const vector<Vec3> &vrts, const vector< vector<int> > &idxs, 
                                const vector<Vec3> &nrms, 
                                rxMaterial *gmat, bool select)
{
    int i;
    rxMaterial *mat;
    for(i = 0; i < (int)idxs.size(); ++i){
        if(gmat == NULL){
            mat = &g_matDefault;
        }
        else{
            mat = gmat;
        }
        
        if(select) glLoadName(i);
        mat->SetGL();
        glEnable(GL_LIGHTING);
        DrawPolygonGouraud(vrts, idxs[i], nrms, mat->GetDiff3());
    }
}

傾いた直方体描画

glRotate使用版

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22

inline void DrawSolidCuboid(Vec3 cen, Vec3 len, Vec3 dir)
{
    Vec3 org_axis(1.0, 0.0, 0.0);
    Vec3 tgt_axis = Unit(dir);
 
    Vec3 rot_axis = Unit(cross(org_axis, tgt_axis));
    double rot_angle = acos((double)(dot(org_axis, tgt_axis)));
 
    glPushMatrix();
    glTranslatef(cen[0], cen[1], cen[2]);
    glRotatef(RX_TO_DEGREES(rot_angle), rot_axis[0], rot_axis[1], rot_axis[2]);
 
    DrawSolidCuboid(Vec3(0.0), len);
 
    glPopMatrix();
}

コーナー座標値算出版

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63

inline void DrawSolidCuboid(Vec3 cen, Vec3 len, Vec3 dir)
{
    len *= 0.5;
    dir = Unit(dir);
 
    Vec3 up(0.0, 1.0, 0.0);
    Vec3 right = cross(dir, up);
 
    Vec3 nc = cen-dir*len[0];
    Vec3 fc = cen+dir*len[0];
 
    right = Unit(right);
    up = Unit(cross(right, dir));
 
    Vec3 corner[8];
    corner[0] = nc-up*len[1]-right*len[2];
    corner[1] = nc+up*len[1]-right*len[2];
    corner[2] = nc+up*len[1]+right*len[2];
    corner[3] = nc-up*len[1]+right*len[2];
 
    corner[4] = fc-up*len[1]-right*len[2];
    corner[5] = fc+up*len[1]-right*len[2];
    corner[6] = fc+up*len[1]+right*len[2];
    corner[7] = fc-up*len[1]+right*len[2];
 
    int index[6][4] = { { 3, 2, 1, 0 }, 
                        { 4, 5, 6, 7 }, 
                        { 3, 0, 4, 7 }, 
                        { 1, 2, 6, 5 }, 
                        { 0, 1, 5, 4 }, 
                        { 2, 3, 7, 6 } }; 
 
 
    glPushMatrix();
    glBegin(GL_QUADS);
 
        glNormal3dv((-dir).data);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[0][i]].data);
    glNormal3dv(dir.data);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[1][i]].data);
 
        glNormal3dv((-up).data);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[2][i]].data);
    glNormal3dv(up.data);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[3][i]].data);
 
        glNormal3dv((-right).data);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[4][i]].data);
    glNormal3dv(right.data);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[5][i]].data);
 
    glEnd();
    glPopMatrix();
}

直方体描画

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51

inline void DrawSolidCuboid(Vec3 &cen, Vec3 len)
{
    len *= 0.5;
    Vec3 corner[8];
 
    corner[0] = cen+Vec3(-len[0], -len[1], -len[2]);
    corner[1] = cen+Vec3(-len[0],  len[1], -len[2]);
    corner[2] = cen+Vec3(-len[0],  len[1],  len[2]);
    corner[3] = cen+Vec3(-len[0], -len[1],  len[2]);
 
    corner[4] = cen+Vec3( len[0], -len[1], -len[2]);
    corner[5] = cen+Vec3( len[0],  len[1], -len[2]);
    corner[6] = cen+Vec3( len[0],  len[1],  len[2]);
    corner[7] = cen+Vec3( len[0], -len[1],  len[2]);
 
    int index[6][4] = { { 3, 2, 1, 0 }, 
                        { 4, 5, 6, 7 }, 
                        { 3, 0, 4, 7 }, 
                        { 1, 2, 6, 5 }, 
                        { 0, 1, 5, 4 }, 
                        { 2, 3, 7, 6 } }; 
 
    glPushMatrix();
    glBegin(GL_QUADS);
 
        glNormal3d(-1.0, 0.0, 0.0);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[0][i]].data);
    glNormal3d( 1.0, 0.0, 0.0);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[1][i]].data);
 
        glNormal3d(0.0, -1.0, 0.0);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[2][i]].data);
    glNormal3d(0.0,  1.0, 0.0);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[3][i]].data);
 
        glNormal3d(0.0, 0.0, -1.0);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[4][i]].data);
    glNormal3d(0.0, 0.0,  1.0);
    for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[5][i]].data);
 
    glEnd();
    glPopMatrix();
}

立方体描画(ディスプレイリスト使用)

vector<Vec3>は配列にした方が効率がよいかも.scaleやwireは最初の描画時に指定した値が反映される.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
static void DrawCube(double scale = 0.5, bool wire = false)
{
    using namespace boost::assign;
 
    static GLuint polyList = 0;
    
    vector<Vec3> vrts, cols;
    vrts += Vec3( 1.0,  1.0,  1.0), \
            Vec3( 1.0, -1.0,  1.0), \
            Vec3(-1.0, -1.0,  1.0), \
            Vec3(-1.0,  1.0,  1.0), \
            Vec3( 1.0,  1.0, -1.0), \
            Vec3( 1.0, -1.0, -1.0), \
            Vec3(-1.0, -1.0, -1.0), \
            Vec3(-1.0,  1.0, -1.0);
 
    cols += Vec3(1.0, 1.0, 1.0), \
            Vec3(1.0, 1.0, 0.0), \
            Vec3(0.0, 1.0, 0.0), \
            Vec3(0.0, 1.0, 1.0), \
            Vec3(1.0, 0.0, 1.0), \
            Vec3(1.0, 0.0, 0.0), \
            Vec3(0.0, 0.0, 0.0), \
            Vec3(0.0, 0.0, 1.0);
 
    const short faces[6][4] = { {3, 2, 1, 0}, 
                                {2, 3, 7, 6}, 
                                {0, 1, 5, 4}, 
                                {3, 0, 4, 7}, 
                                {1, 2, 6, 5}, 
                                {4, 5, 6, 7} };
    GLint num_faces = 6;
    
    if(!polyList){
 
        polyList = glGenLists(1);
        glNewList(polyList, GL_COMPILE);
 
        if(!wire){
            glBegin(GL_QUADS);
            for(int f = 0; f < num_faces; ++f){
                for(int i = 0; i < 4; ++i){
                    glColor3dv(cols[faces[f][i]].data);
                    glVertex3dv((vrts[faces[f][i]]*scale).data);
                }
            }
            glEnd();
        }
 
        glColor3f(0.0, 0.0, 0.0);
        for(int f = 0; f < num_faces; ++f){
            glBegin(GL_LINE_LOOP);
            for(int i = 0; i < 4; ++i){
                glVertex3dv((vrts[faces[f][i]]*scale).data);
            }
            glEnd();
        }
        glEndList();
    }
    
    glPushMatrix();
    glCallList(polyList);
    glPopMatrix();
}

円筒描画

DrawCylinderは円筒,DrawCapsuleは両端が半球状の円筒.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89

static void DrawCylinder(double rad, double len, int axis, int slices)
{
    GLUquadricObj *qobj;
    qobj = gluNewQuadric();
 
    glPushMatrix();
    switch(axis){
    case 0:
        glRotatef(-90.0, 0.0, 1.0, 0.0);
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    case 1:
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    case 2:
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    default:
        glTranslatef(0.0, 0.0, -0.5*len);
    }
 
    gluQuadricDrawStyle(qobj, GLU_FILL);
    gluQuadricNormals(qobj, GLU_SMOOTH);
    gluCylinder(qobj, rad, rad, len, slices, slices);
 
    glPushMatrix();
    glRotatef(180.0, 1.0, 0.0, 0.0);
    gluDisk(qobj, 0.0, rad, slices, slices);
    glPopMatrix();
 
    glPushMatrix();
    glTranslatef(0.0, 0.0, len);
    gluDisk(qobj, 0.0, rad, slices, slices);
    glPopMatrix();
 
    glPopMatrix();
}
 

static void DrawCapsule(double rad, double len, int axis, int slices)
{
    GLUquadricObj *qobj;
    qobj = gluNewQuadric();
 
    glPushMatrix();
    switch(axis){
    case 0:
        glRotatef(-90.0, 0.0, 1.0, 0.0);
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    case 1:
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    case 2:
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    default:
        glTranslatef(0.0, 0.0, -0.5*len);
    }
 
    gluQuadricDrawStyle(qobj, GLU_FILL);
    gluQuadricNormals(qobj, GLU_SMOOTH);
    gluCylinder(qobj, rad, rad, len, slices, slices);
 
    glPushMatrix();
    glutSolidSphere(rad, slices, slices);
    glPopMatrix();
 
    glPushMatrix();
    glTranslatef(0.0, 0.0, len);
    glutSolidSphere(rad, slices, slices);
    glPopMatrix();
 
    glPopMatrix();
 
}

ワイヤフレーム描画時に不自然にならないように両端の球をちゃんと半球として描画したい場合.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55

void DrawCapsule(double rad, double len, int axis, int slices)
{
    GLUquadricObj *qobj;
    qobj = gluNewQuadric();
 
    glPushMatrix();
    switch(axis){
    case 0:
        glRotatef(-90.0, 0.0, 1.0, 0.0);
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    case 1:
        glRotatef(-90.0, 1.0, 0.0, 0.0);
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    case 2:
        glTranslatef(0.0, 0.0, -0.5*len);
        break;
    default:
        glTranslatef(0.0, 0.0, -0.5*len);
    }
 
    gluQuadricDrawStyle(qobj, GLU_FILL);
    gluQuadricNormals(qobj, GLU_SMOOTH);
    gluCylinder(qobj, rad, rad, len, slices, slices);
 
    double c_init[4] = {0, 0, 0, 0};
    double c_bottom[4] = {0, 0, -1, 0};
    double c_top[4] = {0, 0, 1, 0};
 
    glEnable(GL_CLIP_PLANE0);
 
    glPushMatrix();
    glClipPlane(GL_CLIP_PLANE0, c_bottom);
    glutSolidSphere(rad, slices, slices);
    glPopMatrix();
 
    glPushMatrix();
    glTranslatef(0.0, 0.0, len);
    glClipPlane(GL_CLIP_PLANE0, c_top);
    glutSolidSphere(rad, slices, slices);
    glPopMatrix();
 
    glClipPlane(GL_CLIP_PLANE0, c_init);
    glDisable(GL_CLIP_PLANE0);
     
    glPopMatrix();
}

GLUを使わないで円筒を描画する場合. z軸平行で描画される.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60

void DrawCylinder(double r, double h, int slice)
{
    double theta = 2.0*RX_PI/(double)slice;
    double n_norm;
 
    Vec3 origin = Vec3(0.0);
 
    vector<Vec3> vert;
    vert.resize(slice);
    Vec3 normal;
 
    glPushMatrix();
    
        glNormal3f(0.0, 1.0, 0.0);
    glBegin(GL_POLYGON);
    for(int i = 0; i < slice; ++i){
        vert[i][0] = origin[0]+r*sin(theta*(double)i);
        vert[i][1] = origin[1]+r*cos(theta*(double)i);
        vert[i][2] = origin[2]+h;
        glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
    }
    glEnd();
 
        glNormal3f(0.0, -1.0, 0.0);
    glBegin(GL_POLYGON);
    for(int i = 0; i < slice; ++i){
        vert[i][2] = origin[2];
        glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
    }
    glEnd();
 
        glBegin(GL_QUAD_STRIP);
    int j;
    for(int i = 0; i < slice; ++i){
        j = (i+1)%slice;
        normal = 0.5*(vert[i]+vert[j]);
        normal = origin-normal;
        n_norm = norm(normal);
        if(n_norm > RX_EPS) normal /= n_norm;    
 
        glNormal3f(normal[0], normal[1], normal[2]);
        glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
        glVertex3f(vert[i][0], vert[i][1], vert[i][2]+h);
    }
    glVertex3f(vert[j][0], vert[j][1], vert[j][2]);
    glVertex3f(vert[j][0], vert[j][1], vert[j][2]+h);
    glEnd();
 
    glPopMatrix();
}

キューブマップ描画

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50

void RxGLDraw::DrawCubeMap(GLuint cube_map, double side)
{
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glDisable(GL_CULL_FACE);
 
        glEnable(GL_TEXTURE_CUBE_MAP);
    glBindTexture(GL_TEXTURE_CUBE_MAP, cube_map);
 
        glPushMatrix();
    GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
    GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
    GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
    glTexGenfv(GL_S, GL_OBJECT_PLANE, s_plane);
    glTexGenfv(GL_T, GL_OBJECT_PLANE, t_plane);
    glTexGenfv(GL_R, GL_OBJECT_PLANE, r_plane);
    glPopMatrix();
 
    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
 
    glEnable(GL_TEXTURE_GEN_S);
    glEnable(GL_TEXTURE_GEN_T);
    glEnable(GL_TEXTURE_GEN_R);
 
        glPushMatrix();
    glutSolidCube(side);
    glPopMatrix();
 
    glDisable(GL_TEXTURE_GEN_S);
    glDisable(GL_TEXTURE_GEN_T);
    glDisable(GL_TEXTURE_GEN_R);
 
    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    glDisable(GL_TEXTURE_CUBE_MAP);
 
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
}

矢印描画

2Dの場合

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40

inline static void DrawArrow2D(const Vec2 &s, const Vec2 &e, double scale = 0.2)
{
        Vec2 origin = s;
    Vec2 dir = e-s;
    double length = normalize(dir);
     
        double theta = 180.0/RX_PI*acos(dot(Vec2(1, 0), dir))*RX_SIGN(dir[1]);
    
        double arrow_x = scale*length;                        double arrow_y = arrow_x*0.363970234;         
    glPushMatrix();
 
    glTranslatef(origin[0], origin[1], 0.0);        glRotatef(theta, 0.0, 0.0, 1.0);             
    glBegin(GL_LINES);
        glVertex2d(0.0, 0.0);
    glVertex2d(length, 0.0);
 
        glVertex2d(length, 0.0);
    glVertex2d(length-arrow_x, arrow_y);
    glVertex2d(length, 0.0);
    glVertex2d(length-arrow_x, -arrow_y);
    glEnd();
 
    glPopMatrix();
}

3Dの場合(3DベクトルクラスVec3と上の円筒描画,下の任意ベクトル周りの回転の関数を使用).

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38

void DrawArrow(Vec3 pos, Vec3 vec, double r, double dr = 2.5, double dl = 0.1)
{
    double vlen = norm(vec);
    Vec3 pos1 = pos+vec*(1.0-dl*0.5);
 
    Vec3 init = Vec3(0.0, 0.0, 1.0);     
        double rot_ang = acos(dot(init, Unit(vec)))*57.295779513082320876798154814114;
    Vec3 rot_axis = Unit(cross(init, Unit(vec)));
 
    glPushMatrix();
 
    glTranslatef(pos[0], pos[1], pos[2]);        glRotatef(rot_ang, rot_axis[0], rot_axis[1], rot_axis[2]);     
        DrawCylinder(r, vlen*(1.0-dl*0.5), 16);
 
        double alen = dl*vlen;        double arad = dr*r;         
    pos1 = pos+vec;
 
    glTranslatef(0.0, 0.0, vlen-alen);
    glutSolidCone(arad, alen, 16, 16);
 
    glPopMatrix();
}

文字描画

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38

呼び出す前にglColorで色の設定をしておく.

boost::circular_bufferを使ってコマンドプロンプトのように文字列を次々と描画していく.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
typedef boost::circular_buffer<string> CircularBuf;
 
static CircularBuf g_cbDrawDef(5);
static vector<string> g_cbDrawStaticDef(3);
 
template<typename T>
inline CircularBuf &operator<<(CircularBuf &cb, const T &a)
{
    string buf = boost::lexical_cast<std::string>(a);
    if(buf == "\n"){
        cb.push_back("");
    }
    else if(cb.empty()){
        cb.push_back(buf);
    }
    else{
        cb.back() += buf;
    }
    return cb;
}
 
template<typename T>
inline string &operator<<(string &cb, const T &a)
{
    cb += boost::lexical_cast<std::string>(a);
    return cb;
}
 
 
 

static void DrawStrings(CircularBuf cir_str, vector<string> &static_str, int w, int h)
{
    // MRK:PrintD
    glDisable(GL_LIGHTING);
    //glColor3f(0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    gluOrtho2D(0, w, 0, h);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
 
    float x0 = 5;
    float y0 = h-20;
 
        for(int j = 0; j < (int)static_str.size(); ++j){
        glRasterPos2f(x0, y0);
 
        int size = (int)static_str[j].size();
        for(int i = 0; i < size; ++i){
            char ic = static_str[j][i];
            glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ic);
        }
 
        y0 -= 20;
    }
 
        x0 = 5;
    y0 = 20*cir_str.size();;
    for(int j = 0; j < (int)cir_str.size(); ++j){
        glRasterPos2f(x0, y0);
 
        int size = (int)cir_str[j].size();
        for(int i = 0; i < size; ++i){
            char ic = cir_str[j][i];
            glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ic);
        }
 
        y0 -= 20;
    }
 
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
}

三角形メッシュ描画(法線計算付き)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45

void DrawMesh(const vector<Vec3> &vrts, const vector< vector<int> > &idxes, bool normal)
{
    for(int i = 0; i < (int)idxes.size(); ++i){
        vector<int> idx = idxes[i];
        int nv = (int)idx.size();
 
                Vec3 nrm;
        nrm = cross(vrts[idx[1]]-vrts[idx[0]], vrts[idx[nv-1]]-vrts[idx[0]]);
        normalize(nrm);
 
        if(normal){
                        Vec3 mc(0.0);
            for(int j = 0; j < nv; ++j){
                mc += vrts[idx[j]];
            }
            mc /= (double)nv;
 
            int lighting = glIsEnabled(GL_LIGHTING);
            glDisable(GL_LIGHTING);
            glBegin(GL_LINES);
            glVertex3dv(mc.data);
            glVertex3dv((mc+0.05*nrm).data);
            glEnd();
 
            lighting ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING);
        }
 
        glNormal3dv(nrm.data);
 
                glBegin(GL_POLYGON);
        for(int j = 0; j < nv; ++j){
            glVertex3dv(vrts[idx[j]].data);
        }
        glEnd();
    }
}

法線は面の重心に描画される.Vec3はオペレータ[]で各要素にアクセスできる3次元ベクトルクラス.

球の描画

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14

inline void DrawSphere(const Vec3 &cen, const double &rad, const Vec4 &col)
{
    glPushMatrix();
    glTranslatef(cen[0], cen[1], cen[2]);
    glRotated(90, 1.0, 0.0, 0.0);
    glutSolidSphere(rad, 20, 10);
    glPopMatrix();
}

球の(滑らかな)ワイヤーフレーム描画

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78

static void DrawWireCircle(const double &rad, const int &n)
{
    double t = 0.0;
    double dt = 2.0*RX_PI/(double)n;
 
    glBegin(GL_LINE_LOOP);
    do{
        glVertex3f(rad*cos(t), rad*sin(t), 0.0);
        t += dt;
    }while(t < 2.0*RX_PI);
    glEnd();
}
 

static void DrawWireCircleXZ(const double &rad, const int &n)
{
    double t = 0.0;
    double dt = 2.0*RX_PI/(double)n;
 
    glBegin(GL_LINE_LOOP);
    do{
        glVertex3f(rad*cos(t), 0.0, rad*sin(t));
        t += dt;
    }while(t < 2.0*RX_PI);
    glEnd();
}
 

void DrawWireSphere(const Vec3 &cen, const float &rad, const Vec3 &col)
{
    glDisable(GL_LIGHTING);
    glPushMatrix();
    glTranslatef(cen[0], cen[1], cen[2]);
    glRotatef(90, 1.0, 0.0, 0.0);
    glColor3f(col[0], col[1], col[2]);
 
        float z, dz;
    dz = 2.0*rad/8.0f;
    z = -(rad-dz);
    do{
        glPushMatrix();
        glTranslatef(0.0, 0.0, z);
        DrawWireCircle(sqrt(rad*rad-z*z), 32);
        glPopMatrix();
        z += dz;
    }while(z < rad);
 
        float t, dt;
    t = 0.0f;
    dt = 180.0/8.0;
    do{
        glPushMatrix();
        glRotatef(t,  0.0, 0.0, 1.0);
        DrawWireCircleXZ(rad, 32);
        glPopMatrix();
 
        t += dt;
    }while(t < 180);
 
    //glutWireSphere(rad, 10, 5);
    glPopMatrix();
}

円の描画

x-y平面上に円を描画.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47

static void DrawCircle(Vec3 cen, double rad, int n)
{
    double t = 0.0;
    double dt = 2.0*RX_PI/(double)n;
 
    glPushMatrix();
 
    glTranslatef(cen[0], cen[1], cen[2]);
    glBegin(GL_POLYGON);
    do{
        glVertex3f(rad*cos(t), rad*sin(t), 0.0);
        t += dt;
    }while(t < 2.0*RX_PI);
    glEnd();
 
    glPopMatrix();
}
 

static void DrawWireCircle(Vec3 cen, double rad, int n)
{
    double t = 0.0;
    double dt = 2.0*RX_PI/(double)n;
 
    glPushMatrix();
 
    glTranslatef(cen[0], cen[1], cen[2]);
    glBegin(GL_LINE_LOOP);
    do{
        glVertex3f(rad*cos(t), rad*sin(t), 0.0);
        t += dt;
    }while(t < 2.0*RX_PI);
    glEnd();
 
    glPopMatrix();
}

Vec3はオペレータ[]で各要素にアクセスできる3次元ベクトルクラス.RX_PIは円周率.

アフィン変換

回転

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
const double RX_DEGREES_TO_RADIANS = 0.0174532925199432957692369076848;
 
template<class T> 
inline T RX_TO_RADIANS(const T &x){ return static_cast<T>((x)*RX_DEGREES_TO_RADIANS); }
 

inline Vec3 RxRotate(const Vec3 &pos, const Vec3 &rot_deg)
{
    Vec3 pos1;
    Vec3 rot = RX_TO_RADIANS(rot_deg);
    Vec3 S(sin(rot[0]), sin(rot[1]), sin(rot[2]));
    Vec3 C(cos(rot[0]), cos(rot[1]), cos(rot[2]));
    pos1[0] =                   C[1]*C[2]*pos[0]                   -C[1]*S[2]*pos[1]      +S[1]*pos[2];
    pos1[1] =  (S[0]*S[1]*C[2]+C[0]*S[2])*pos[0] +(-S[0]*S[1]*S[2]+C[0]*C[2])*pos[1] -S[0]*C[1]*pos[2];
    pos1[2] = (-C[0]*S[1]*C[2]+S[0]*S[2])*pos[0]  +(C[0]*S[1]*S[2]+S[0]*C[2])*pos[1] +C[0]*C[1]*pos[2];
    return pos1;
}
 

inline Vec2 RxRotate2D(const Vec2 &pos, double rot_deg)
{
    double rot = RX_TO_RADIANS(rot_deg);
    return Vec2(pos[0]*cos(rot)-pos[1]*sin(rot), pos[0]*sin(rot)+pos[1]*cos(rot));
}

任意ベクトル周りの回転

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27

inline Vec3 Rotate(const Vec3 &pos, const Vec3 &axis, const double &ang_deg)
{
    Vec3 pos1;        double ang = RX_TO_RADIANS(ang_deg);
 
    double c = cos(ang);
    double s = sin(ang);
    double x, y, z;
    x = axis[0]; y = axis[1]; z = axis[2];
    
    // | xx(1-c)+c    xy(1-c)-zs    xz(1-c)+ys    0 |
    // | yx(1-c)+zs    yy(1-c)+c    yz(1-c)-xs    0 |
    // | xz(1-c)-ys    yz(1-c)+xs    zz(1-c)+c    0 |
    // | 0            0            0            1 |
    pos1[0] =   (x*x*(1.0-c)+c)*pos[0] +(x*y*(1.0-c)-z*s)*pos[1] +(x*z*(1.0-c)+y*s)*pos[2];
    pos1[1] = (y*x*(1.0-c)+z*s)*pos[0]   +(y*y*(1.0-c)+c)*pos[1] +(y*z*(1.0-c)-x*s)*pos[2];
    pos1[2] = (x*z*(1.0-c)-y*s)*pos[0] +(y*z*(1.0-c)+x*s)*pos[1]   +(z*z*(1.0-c)+c)*pos[2];
 
    return pos1;
}

オイラー角から回転行列

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44

inline void EulerToMatrix(double *m, double pitch, double yaw, double roll)
{
    yaw   = RX_TO_RADIANS(yaw);
    pitch = RX_TO_RADIANS(pitch);
    roll  = RX_TO_RADIANS(roll);
 
    double cy = cos(yaw); 
    double sy = sin(yaw); 
    double cp = cos(pitch); 
    double sp = sin(pitch); 
    double cr = cos(roll);
    double sr = sin(roll);
 
    double cc = cy*cr; 
    double cs = cy*sr; 
    double sc = sy*cr; 
    double ss = sy*sr;
 
    m[0]  = cc+sp*ss;
    m[1]  = cs-sp*sc;
    m[2]  = -sy*cp;
    m[3]  = 0.0;
    
    m[4]  = -cp*sr;
    m[5]  = cp*cr; 
    m[6]  = -sp;
    m[7]  = 0.0;
    
    m[8]  = sc-sp*cs;
    m[9]  = ss+sp*cc;
    m[10] = cy*cp;
    m[11] = 0.0;
 
    m[12] = 0.0;
    m[13] = 0.0;
    m[14] = 0.0;
    m[15] = 1.0;
}

射影

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30

inline void ProjectShadowMatrix(double *m, double plane[4], double light[4])
{
    double dot = plane[0]*light[0]+plane[1]*light[1]+plane[2]*light[2]+plane[3]*light[3];
 
    m[0]  = dot-light[0]*plane[0];
    m[4]  =    -light[0]*plane[1];
    m[8]  =    -light[0]*plane[2];
    m[12] =    -light[0]*plane[3];
 
    m[1]  =    -light[1]*plane[0];
    m[5]  = dot-light[1]*plane[1];
    m[9]  =    -light[1]*plane[2];
    m[13] =    -light[1]*plane[3];
 
    m[2]  =    -light[2]*plane[0];
    m[6]  =    -light[2]*plane[1];
    m[10] = dot-light[2]*plane[2];
    m[14] =    -light[2]*plane[3];
 
    m[3]  =    -light[3]*plane[0];
    m[7]  =    -light[3]*plane[1];
    m[11] =    -light[3]*plane[2];
    m[15] = dot-light[3]*plane[3];
}

その他関数

球形状ポリゴン生成

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

int MakeSphere(double rad, int slices, int stacks, 
               vector<Vec3> &vrts, vector<Vec3> &nrms, vector<Vec2> &txcs, vector< vector<int> > &fces, 
               bool tri = true)
{
    int vn = 2+(stacks-1)*slices;            vrts.resize(vn, Vec3(0.0));        nrms.resize(vn, Vec3(0.0));        txcs.resize(vn, Vec2(0.0));     
    vrts[0]    = Vec3(0.0, 0.0,  rad);        vrts[vn-1] = Vec3(0.0, 0.0, -rad);     
    double dp = RX_PI/(double)stacks;            double dt = 2.0*RX_PI/(double)slices;     
    double phi = dp;        double theta = 0.0;     
        for(int i = 0; i < stacks-1; ++i){
        double z = rad*cos(phi);
        theta = 0.0;
        for(int j = 0; j < slices; ++j){
            double rad_t = rad*sin(phi);
 
            int idx = 1+i*slices+j;
            vrts[idx] = Vec3(rad_t*cos(theta), rad_t*sin(theta), z);
            nrms[idx] = Unit(vrts[idx]);
            txcs[idx] = Vec2(theta/(2.0*RX_PI), phi/(RX_PI));
 
            theta += dt;
        }
        phi += dp;
    }
 
        int fn = 2*slices+(stacks-2)*slices*(tri ? 2 : 1);
    fces.reserve(fn);
 
        for(int i = 0; i < stacks; ++i){
        if(i == 0){                vector<int> f(3);
            for(int j = 0; j < slices; ++j){
                int k0 = 1+i*slices+j;
                int k1 = 1+i*slices+(j == slices-1 ? 0 : j+1);
                f[0] = 0; f[1] = k0; f[2] = k1;
                fces.push_back(f);
            }
        }
        else if(i == stacks-1){                vector<int> f(3);
            for(int j = 0; j < slices; ++j){
                int k0 = 1+(i-1)*slices+j;
                int k1 = 1+(i-1)*slices+(j == slices-1 ? 0 : j+1);
                f[0] = vn-1; f[1] = k1; f[2] = k0;
                fces.push_back(f);
            }
        }
        else{
            for(int j = 0; j < slices; ++j){
                int k0 = 1+i*slices+j;
                int k1 = 1+i*slices+(j == slices-1 ? 0 : j+1);
                int k2 = 1+(i-1)*slices+j;
                int k3 = 1+(i-1)*slices+(j == slices-1 ? 0 : j+1);
 
                vector<int> f;
                if(tri){
                                        f.resize(3);
                    f[0] = k0; f[1] = k1; f[2] = k3;
                    fces.push_back(f);
                    f[0] = k0; f[1] = k3; f[2] = k2;
                    fces.push_back(f);
                }
                else{
                                        f.resize(4);
                    f[0] = k0; f[1] = k1; f[2] = k3; f[3] = k2;
                    fces.push_back(f);
                }
            }
        }
    }
 
    return 0;
}
 

int MakeSphereC(double rad, int slices, int stacks, 
                vector<Vec3> &vrts, vector<Vec3> &nrms, vector<Vec2> &txcs, vector< vector<int> > &fces, 
                bool tri = true)
{
    int vn = (stacks+1)*(slices+1);            vrts.resize(vn, Vec3(0.0));        nrms.resize(vn, Vec3(0.0));        txcs.resize(vn, Vec2(0.0));     
    double dp = RX_PI/(double)stacks;            double dt = 2.0*RX_PI/(double)slices;     
    double phi = 0;            double theta = 0.0;     
        for(int i = 0; i < stacks+1; ++i){
        double z = rad*cos(phi);
        theta = 0.0;
        for(int j = 0; j < slices+1; ++j){
            double rad_t = rad*sin(phi);
 
            int idx = i*(slices+1)+j;
            vrts[idx] = Vec3(rad_t*cos(theta), rad_t*sin(theta), z);
            nrms[idx] = Unit(vrts[idx]);
            txcs[idx] = Vec2(theta/(2.0*RX_PI), phi/(RX_PI));
 
            theta += dt;
        }
        phi += dp;
    }
 
        int fn = stacks*slices*(tri ? 2 : 1);
    fces.reserve(fn);
 
        for(int i = 1; i < stacks+1; ++i){
        for(int j = 0; j < slices; ++j){
            int k0 = i*(slices+1)+j;
            int k1 = i*(slices+1)+(j+1);
            int k2 = (i-1)*(slices+1)+j;
            int k3 = (i-1)*(slices+1)+(j+1);
 
            vector<int> f;
            if(tri){
                                f.resize(3);
                f[0] = k0; f[1] = k1; f[2] = k3;
                fces.push_back(f);
                f[0] = k0; f[1] = k3; f[2] = k2;
                fces.push_back(f);
            }
            else{
                                f.resize(4);
                f[0] = k0; f[1] = k1; f[2] = k3; f[3] = k2;
                fces.push_back(f);
            }
        }
    }
    return 0;
}

ミップマップテクスチャのサイズの計算

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11

inline int CalMipmapSize(const int &x, int &d)
{
    d = (int)(log((double)x)/log(2.0));
    return (int)pow(2.0, (double)d);
}

グラデーション色の作成

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
template<class T> 
inline T RX_CLAMP(const T &x, const T &a, const T &b){ return ((x < a) ? a : (x > b) ? b : x); }
 
template<class T>
inline T RX_LERP(const T &a, const T &b, const T &t){ return a + t*(b-a); }
 

inline void CalThermograph(double col[3], double x, const double xmin = 0.0, const double xmax = 1.0)
{
    double l = xmax-xmin;
    if(fabs(l) < 1e-10) return;
    
    const int ncolors = 7;
    double base[ncolors][3] = { {0.0, 0.0, 0.0},
                                {0.0, 0.0, 1.0},
                                {0.0, 1.0, 1.0},
                                {0.0, 1.0, 0.0},
                                {1.0, 1.0, 0.0},
                                {1.0, 0.0, 0.0},
                                {1.0, 1.0, 1.0} };
    x = RX_CLAMP(((x-xmin)/l), 0.0, 1.0)*(ncolors-1);
    int i = (int)x;
    double dx = x-floor(x);
    col[0] = RX_LERP(base[i][0], base[i+1][0], dx);
    col[1] = RX_LERP(base[i][1], base[i+1][1], dx);
    col[2] = RX_LERP(base[i][2], base[i+1][2], dx);
}
 

inline void CalGradation(double col[3], const double col1[3], const double col2[3], 
                         double x, const double xmin = 0.0, const double xmax = 1.0)
{
    double l = xmax-xmin;
    if(fabs(l) < 1e-10) return;
    
    double dx = RX_CLAMP(((x-xmin)/l), 0.0, 1.0);
    col[0] = RX_LERP(col1[0], col2[0], dx);
    col[1] = RX_LERP(col1[1], col2[1], dx);
    col[2] = RX_LERP(col1[2], col2[2], dx);
}

クラス

テクスチャ管理クラス

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class rxTexObj
{
protected:
    GLenum m_iTarget;
    bool m_bValid;
    bool m_bManageObjects;
    GLuint m_iTexName;
 
 
public:
        rxTexObj(GLenum tgt, bool managed) : m_iTarget(tgt), m_bValid(false), m_bManageObjects(managed) {}
 
    ~rxTexObj()
    {
        if(m_bManageObjects) Delete();
    }
 
    void Bind(void)
    {
        if(!m_bValid){
            Generate();
        }
        glBindTexture(m_iTarget, m_iTexName);
    }
 
    void UnBind(void)
    {
        glBindTexture(m_iTarget, 0);
    }
 
    void SetParameter(GLenum pname, GLint i){ glTexParameteri(m_iTarget, pname, i); }
    void SetParameter(GLenum pname, GLfloat f){ glTexParameterf(m_iTarget, pname, f);    }
    void SetParameter(GLenum pname, GLint *ip){ glTexParameteriv(m_iTarget, pname, ip); }
    void SetParameter(GLenum pname, GLfloat *fp){ glTexParameterfv(m_iTarget, pname, fp); }
 
    void Enable(void){ glEnable(m_iTarget); }
    void Disable(void){ glDisable(m_iTarget); }
 
    GLuint GetTexName(void) const { return m_iTexName; }
    GLenum GetTexTarget(void) const { return m_iTarget; }
 
    void Delete()
    {
        if(m_bValid){
            glDeleteTextures(1, &m_iTexName);
            m_bValid = false; 
        }
    }
            
    void Generate()
    { 
        glGenTextures(1, &m_iTexName);
        m_bValid = true;
    }
 
public:
    bool IsValid() const { return m_bValid; }
};
 
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
template <class T>
class rxTexObj2D_T : public rxTexObj
{
public:
    T *m_pImage;
    int m_iW, m_iH, m_iC;
    GLenum m_iFormat;
 
public:
        rxTexObj2D_T(bool managed = false) : rxTexObj(GL_TEXTURE_2D, managed)
    {
        m_pImage = NULL;
        m_iW = 0;
        m_iH = 0;
        m_iC = 3;
        m_iFormat = GL_RGB;
    }
 
        ~rxTexObj2D_T()
    {
        if(m_pImage != NULL) delete [] m_pImage;
    }
 
 
    
    void SetSize(int iW, int iH, int iC = 3)
    {
        if(m_iW != iW || m_iH != iH || m_iC != iC){
            m_iW = iW;
            m_iH = iH;
            m_iC = iC;
            m_iFormat = (m_iC == 4) ? GL_RGBA : GL_RGB;
 
            if(m_pImage != NULL) delete [] m_pImage;
            m_pImage = new T[m_iW*m_iH*m_iC];
        }
    }
 
    
    void GetSize(int &iW, int &iH, int &iC)
    {
        iW = m_iW;
        iH = m_iH;
        iC = m_iC;
    }
 
    
    void GetColor(int ic, int jc, T &r, T &g, T &b)
    {
        r = m_pImage[m_iC*(m_iW*jc+ic)+0];
        g = m_pImage[m_iC*(m_iW*jc+ic)+1];
        b = m_pImage[m_iC*(m_iW*jc+ic)+2];
    }
 
    
    void GetColor4(int ic, int jc, T &r, T &g, T &b, T &a)
    {
        r = m_pImage[m_iC*(m_iW*jc+ic)+0];
        g = m_pImage[m_iC*(m_iW*jc+ic)+1];
        b = m_pImage[m_iC*(m_iW*jc+ic)+2];
        if(m_iC == 4) a = m_pImage[m_iC*(m_iW*jc+ic)+3];
    }
 
    
    void SetColor(int ic, int jc, const T &r, const T &g, const T &b)
    {
        m_pImage[m_iC*(m_iW*jc+ic)+0] = r;
        m_pImage[m_iC*(m_iW*jc+ic)+1] = g;
        m_pImage[m_iC*(m_iW*jc+ic)+2] = b;
        if(m_iC == 4) m_pImage[m_iC*(m_iW*jc+ic)+3] = 0;
    }
 
    
    void SetColor(int ic, int jc, const T &r, const T &g, const T &b, const T &a)
    {
        m_pImage[m_iC*(m_iW*jc+ic)+0] = r;
        m_pImage[m_iC*(m_iW*jc+ic)+1] = g;
        m_pImage[m_iC*(m_iW*jc+ic)+2] = b;
        if(m_iC == 4) m_pImage[m_iC*(m_iW*jc+ic)+3] = a;
    }
 
    
    void SetTexture(void){
        GLenum type = GL_UNSIGNED_BYTE;
 
        if(sizeof(T) == 1){
            type = GL_UNSIGNED_BYTE;
        }
        else if(sizeof(T) == 4){
            type = GL_FLOAT;
        }
        
        glTexImage2D(m_iTarget, 0, GL_RGBA, m_iW, m_iH, 0, m_iFormat, type, m_pImage);
    }
 
};
 
typedef rxTexObj2D_T<unsigned char> rxTexObj2D;
typedef rxTexObj2D_T<float> rxTexObj2Df;

材質クラス

OpenGLでの表面材質を管理するクラス. g_matDefaultはデフォルトマテリアルを定義している.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class rxMaterial
{
public:
    Vec4 m_vDiff, m_vSpec, m_vAmbi, m_vEmit;
    double m_fDiffS, m_fSpecS, m_fAmbiS, m_fEmitS;
    double m_fShin;
 
    Vec4 m_vColor;
 
        double m_fEta;            double m_fBias;            double m_fPower;        double m_fScale;     
    string m_strName;
    int m_iID;
 
    int m_iIllum;
    string m_strTexFile;
    unsigned int m_uTexName;
 
public:
    rxMaterial()
    {
        SetColor(Vec3(0.0, 0.0, 1.0), Vec3(1.0), Vec3(1.0), Vec3(0.0), 30.0);
        SetScale(1.0, 0.75, 0.2, 0.0);
        m_fEta = 0.9;
        m_fBias = 1.0;
        m_fPower = 0.98;
        m_fScale = 5.0;
    }
 
    void SetColor(const Vec4 &diff, const Vec4 &spec, const Vec4 &ambi, const Vec4 &emit, const double &shin)
    {
        m_vDiff = diff;
        m_vSpec = spec;
        m_vAmbi = ambi;
        m_vEmit = emit;
        m_fShin = shin;
    }
 
    void SetColor(const GLfloat diff[4], 
                  const GLfloat spec[4], 
                  const GLfloat ambi[4], 
                  const GLfloat emit[4], 
                  const GLfloat shine)
    {
        m_vDiff = Vec4(diff[0], diff[1], diff[2], diff[3]);
        m_vSpec = Vec4(spec[0], spec[1], spec[2], spec[3]);
        m_vAmbi = Vec4(ambi[0], ambi[1], ambi[2], ambi[3]);
        m_vEmit = Vec4(emit[0], emit[1], emit[2], emit[3]);
        m_fShin = shine;
    }
 
    void SetColor(const Vec3 &diff, const Vec3 &spec, const Vec3 &ambi, const Vec3 &emit, const double &shin)
    {
        m_vDiff = diff;    m_vDiff[3] = 1.0;
        m_vSpec = spec;    m_vSpec[3] = 1.0;
        m_vAmbi = ambi;    m_vAmbi[3] = 1.0;
        m_vEmit = emit;    m_vEmit[3] = 1.0;
        m_fShin = shin;
    }
 
    void SetDiff(const Vec4 &col){ m_vDiff = col; }
    void SetSpec(const Vec4 &col){ m_vSpec = col; }
    void SetAmbi(const Vec4 &col){ m_vAmbi = col; }
    void SetEmit(const Vec4 &col){ m_vEmit = col; }
    void SetDiff3(const Vec3 &col){ m_vDiff = col; m_vDiff[3] = 1.0; }
    void SetSpec3(const Vec3 &col){ m_vSpec = col; m_vSpec[3] = 1.0; }
    void SetAmbi3(const Vec3 &col){ m_vAmbi = col; m_vAmbi[3] = 1.0; }
    void SetEmit3(const Vec3 &col){ m_vEmit = col; m_vEmit[3] = 1.0; }
 
    void SetScale(const double &sdiff, const double &sspec, const double &sambi, const double &semit)
    {
        m_fDiffS = sdiff;
        m_fSpecS = sspec;
        m_fAmbiS = sambi;
        m_fEmitS = semit;
     }
 
    void SetRefrac(const double &eta, const double &bias, const double &power, const double &scale)
    {
        m_fEta = eta;
        m_fBias = bias;
        m_fPower = power;
        m_fScale = scale;
     }
 
    void SetGL(void)
    {
        GLfloat mat_diff[] = { (float)(m_fDiffS*m_vDiff[0]), (float)(m_fDiffS*m_vDiff[1]), (float)(m_fDiffS*m_vDiff[2]), (float)m_vDiff[3] };
        GLfloat mat_spec[] = { (float)(m_fSpecS*m_vSpec[0]), (float)(m_fSpecS*m_vSpec[1]), (float)(m_fSpecS*m_vSpec[2]), (float)m_vDiff[3] };
        GLfloat mat_ambi[] = { (float)(m_fAmbiS*m_vAmbi[0]), (float)(m_fAmbiS*m_vAmbi[1]), (float)(m_fAmbiS*m_vAmbi[2]), (float)m_vDiff[3] };
        GLfloat mat_shin[] = { (float)m_fShin };
 
        glMaterialfv(GL_FRONT, GL_DIFFUSE,  mat_diff);
        glMaterialfv(GL_FRONT, GL_SPECULAR, mat_spec);
        glMaterialfv(GL_FRONT, GL_AMBIENT,  mat_ambi); 
        glMaterialfv(GL_FRONT, GL_SHININESS,mat_shin);
 
        glColor3fv(mat_diff);
    }
 
    void SetGL(const Vec4 &diff, const Vec4 &spec, const Vec4 &ambi)
    {
        GLfloat mat_diff[] = { (float)(m_fDiffS*diff[0]), (float)(m_fDiffS*diff[1]), (float)(m_fDiffS*diff[2]), (float)diff[3] };
        GLfloat mat_spec[] = { (float)(m_fSpecS*spec[0]), (float)(m_fSpecS*spec[1]), (float)(m_fSpecS*spec[2]), (float)spec[3] };
        GLfloat mat_ambi[] = { (float)(m_fAmbiS*ambi[0]), (float)(m_fAmbiS*ambi[1]), (float)(m_fAmbiS*ambi[2]), (float)ambi[3] };
        GLfloat mat_shin[] = { (float)m_fShin };
 
        glMaterialfv(GL_FRONT, GL_DIFFUSE,  mat_diff);
        glMaterialfv(GL_FRONT, GL_SPECULAR, mat_spec);
        glMaterialfv(GL_FRONT, GL_AMBIENT,  mat_ambi); 
        glMaterialfv(GL_FRONT, GL_SHININESS,mat_shin);
 
        glColor4fv(mat_diff);
    }
 
        Vec4 GetDiff(void) const { return m_vDiff*m_fDiffS; }
    Vec4 GetSpec(void) const { return m_vSpec*m_fSpecS; }
    Vec4 GetAmbi(void) const { return m_vAmbi*m_fAmbiS; }
    Vec4 GetEmit(void) const { return m_vEmit*m_fEmitS; }
    Vec3 GetDiff3(void) const { return Vec3(m_vDiff[0], m_vDiff[1], m_vDiff[2])*m_fDiffS; }
    Vec3 GetSpec3(void) const { return Vec3(m_vSpec[0], m_vSpec[1], m_vSpec[2])*m_fSpecS; }
    Vec3 GetAmbi3(void) const { return Vec3(m_vAmbi[0], m_vAmbi[1], m_vAmbi[2])*m_fAmbiS; }
    Vec3 GetEmit3(void) const { return Vec3(m_vEmit[0], m_vEmit[1], m_vEmit[2])*m_fEmitS; }
    double GetShin(void) const { return m_fShin; }
 
    Vec3 GetReflec(const Vec3 &irr, const Vec3 &nrm)
    {
        double ref_coef = m_fBias+m_fScale*pow((1.0+dot(irr, nrm)), m_fPower);
        RXFunc::Clamp(ref_coef, 0.0, 1.0);
        return ref_coef*GetSpec3();
    }
 
    Vec3 GetRefrac(const Vec3 &irr, const Vec3 &nrm)
    {
        double ref_coef = m_fBias+m_fScale*pow((1.0+dot(irr, nrm)), m_fPower);
        RXFunc::Clamp(ref_coef, 0.0, 1.0);
        return (1.0-ref_coef)*GetSpec3();
    }
 
    void Get(Vec3 &diff, Vec3 &spec, Vec3 &ambi, Vec3 &emit, double &shin)
    {
        diff = Vec3(m_vDiff[0], m_vDiff[1], m_vDiff[2]);
        spec = Vec3(m_vSpec[0], m_vSpec[1], m_vSpec[2]);
        ambi = Vec3(m_vAmbi[0], m_vAmbi[1], m_vAmbi[2]);
        emit = Vec3(m_vEmit[0], m_vEmit[1], m_vEmit[2]);
        shin = m_fShin;
    }
};
 
static rxMaterial g_matDefault;

マウスピッククラス

コンストラクタかSet関数で描画関数,投影変換関数を指定して, Pick関数にマウス座標(スクリーン座標系)を渡すことで,ポリゴンなどを選択する. クラスに渡す描画関数内ではglLoadNameで各オブジェクトのインデックスを指定しておくこと. Pick関数はこのインデックスを返す.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class rxGLPick
{
    boost::function<void (void)> m_fpDraw;        boost::function<void (void)> m_fpProj;     
    int m_pSelBufferSize;
 
public:
    rxGLPick()
    {
        m_pSelBufferSize = 128;
    }
    rxGLPick(boost::function<void (void)> draw, boost::function<void (void)> proj)
        : m_fpDraw(draw), m_fpProj(proj)
    {
        m_pSelBufferSize = 128;
    }
    ~rxGLPick(){}
 
    void Set(boost::function<void (void)> draw, boost::function<void (void)> proj)
    {
        m_fpDraw = draw;
        m_fpProj = proj;
    }
 
protected:
    
    int selectHits(GLint hits, GLuint buf[])
    {
        GLuint hit_name;
 
        float depth_min = 100.0f;
        float depth1 = 1.0f;
        float depth2 = 1.0f;
 
        GLuint depth_name;
        GLuint *ptr;
        
                if(hits <= 0) return -1;
        
                ptr = (GLuint*)buf;
        for(int i = 0; i < hits; ++i){
                        depth_name = *ptr;
            ptr++;
            depth1 = (float) *ptr/0x7fffffff;
            ptr++;
            depth2 = (float) *ptr/0x7fffffff;
            ptr++;
 
                        if(depth_min > depth1){
                depth_min = depth1;
                hit_name = *ptr;
            }
            ptr++;
        }
        return hit_name;
    }
 
    
    int pick(int x, int y)
    {
        // HCK:Pick
        GLuint* selbuf = new GLuint[m_pSelBufferSize];
        GLint hits;
        GLint viewport[4];
 
        glGetIntegerv(GL_VIEWPORT, viewport);
        glSelectBuffer(m_pSelBufferSize, selbuf);
 
        glRenderMode(GL_SELECT);
 
        glInitNames();
        glPushName(0);
 
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
 
        gluPickMatrix(x, viewport[3]-y, 10.0, 10.0, viewport);
        m_fpProj();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
 
        m_fpDraw();
        glLoadName(0);
 
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glPopName();
 
        hits = glRenderMode(GL_RENDER);
        
        int obj_number = selectHits(hits, selbuf);
        glMatrixMode(GL_MODELVIEW);
 
        return obj_number;
    }
 
 
public:
    
    int Pick(int x, int y)
    {
        int obj_number;
        if((obj_number = pick(x, y)) != -1){
            return obj_number;
        }
        else{
            return -1;
        }
 
            //    object_depth = PickDepth(x,y);
 
        return -1;
    }
};

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2022-11-30 (水) 13:48:08