ENTRYPOINT void init_ball (ModeInfo *mi) { ball_configuration *bp; int wire = MI_IS_WIREFRAME(mi); MI_INIT (mi, bps); bp = &bps[MI_SCREEN(mi)]; bp->glx_context = init_GL(mi); if (! wire) build_texture (mi); reshape_ball (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); bp->th = 180 - frand(360); if (MI_COUNT(mi) < 10) MI_COUNT(mi) = 10; if (MI_COUNT(mi) > 200) MI_COUNT(mi) = 200; { double spin_speed = 0.1; double wander_speed = 0.003; double spin_accel = 1; bp->rot = make_rotator (do_spin ? spin_speed : 0, do_spin ? spin_speed : 0, do_spin ? spin_speed : 0, spin_accel, do_wander ? wander_speed : 0, False); bp->trackball = gltrackball_init (True); } build_ball (mi); if (!wire) { GLfloat color[4] = {0.5, 0.5, 0.5, 1}; GLfloat cspec[4] = {1, 1, 1, 1}; static const GLfloat shiny = 10; static GLfloat pos0[4] = { 0.5, -1, -0.5, 0}; static GLfloat pos1[4] = {-0.75, -1, 0, 0}; static GLfloat amb[4] = {0, 0, 0, 1}; static GLfloat dif[4] = {1, 1, 1, 1}; static GLfloat spc[4] = {1, 1, 1, 1}; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); color[0] += frand(0.2); color[1] += frand(0.2); color[2] += frand(0.2); cspec[0] -= frand(0.2); cspec[1] -= frand(0.2); cspec[2] -= frand(0.2); glLightfv(GL_LIGHT0, GL_POSITION, pos0); glLightfv(GL_LIGHT0, GL_AMBIENT, amb); glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); glLightfv(GL_LIGHT0, GL_SPECULAR, spc); glLightfv(GL_LIGHT1, GL_POSITION, pos1); glLightfv(GL_LIGHT1, GL_AMBIENT, amb); glLightfv(GL_LIGHT1, GL_DIFFUSE, dif); glLightfv(GL_LIGHT1, GL_SPECULAR, spc); glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); glMaterialfv (GL_FRONT, GL_SPECULAR, cspec); glMateriali (GL_FRONT, GL_SHININESS, shiny); } }
// // MQO // void build_from_mqo( mqo_reader::document_type& doc, float scale, const Color& color) { // マテリアル for (const auto& ms: doc.materials) { Piece m; m.vbo = 0; m.ibo = 0; #ifdef JSTEXTURE m.texture = ""; #else m.texture = 0; #endif m.color.rgba[0] = ms.color.red; m.color.rgba[1] = ms.color.green; m.color.rgba[2] = ms.color.blue; m.color.rgba[3] = ms.color.alpha; if (ms.texture != "") { #ifdef JSTEXTURE m.texture = ms.texture; loadTexture(m.texture.c_str()); #else m.texture = build_texture(ms.texture.c_str()); #endif } pieces_.push_back(m); } { // default material Piece m; m.vbo = 0; m.ibo = 0; #ifdef JSTEXTURE m.texture = ""; #else m.texture = 0; #endif m.color = color; pieces_.push_back(m); } // 頂点, 面 for (const auto& pair: doc.objects) { const mqo_reader::object_type& obj = pair.second; // dictionary: // (source vertex index, uv ) => destination vertex index struct VertexKey { int index; float u; float v; VertexKey(){} VertexKey(int aindex, float au, float av) : index(aindex), u(au), v(av) {} bool operator<(const VertexKey& a) const { if (index < a.index) { return true; } if (a.index < index) { return false; } if (u < a.u) { return true; } if (a.u < u) { return false; } return v < a.v; } }; std::vector<std::map<VertexKey, int>> used_vertices; used_vertices.resize(pieces_.size()); // マテリアルごとに使用頂点を分類 for (const auto& face: obj.faces) { int material_index = face.material_index; if (material_index == -1) { material_index = int(pieces_.size() - 1); } int i0 = face.vertex_indices[0]; int i1 = face.vertex_indices[1]; int i2 = face.vertex_indices[2]; std::map<VertexKey, int>& c = used_vertices[material_index]; c[VertexKey(i0, face.uv[0].u, face.uv[0].v)] = -1; c[VertexKey(i1, face.uv[1].u, face.uv[1].v)] = -1; c[VertexKey(i2, face.uv[2].u, face.uv[2].v)] = -1; } // マテリアルごとに使われている頂点を追加 size_t n = pieces_.size(); for (size_t i = 0 ; i < n ; i++) { Piece& m = pieces_[i]; std::map<VertexKey, int>& c = used_vertices[i]; int no = int(m.vertex_source.size()); for (auto& j: c) { const auto& src = obj.vertices[j.first.index]; Piece::Vertex dst; dst.position = Vector( src.x * scale, src.y * scale, src.z * -scale); dst.normal = Vector(0, 0, 0); dst.diffuse = m.color; dst.u = j.first.u; dst.v = j.first.v; m.vertex_source.push_back(dst); j.second = no++; } } // マテリアルごとに面を追加 for (const auto& face: obj.faces) { int material_index = face.material_index; if (material_index == -1) { material_index = int(pieces_.size()- 1); } int i0 = face.vertex_indices[0]; int i1 = face.vertex_indices[1]; int i2 = face.vertex_indices[2]; std::map<VertexKey, int>& c = used_vertices[material_index]; int k0 = c[VertexKey(i0, face.uv[0].u, face.uv[0].v)]; int k1 = c[VertexKey(i1, face.uv[1].u, face.uv[1].v)]; int k2 = c[VertexKey(i2, face.uv[2].u, face.uv[2].v)]; Piece& m = pieces_[material_index]; m.index_source.push_back(k0); m.index_source.push_back(k1); m.index_source.push_back(k2); Piece::Vertex& v0 = m.vertex_source[k0]; Piece::Vertex& v1 = m.vertex_source[k1]; Piece::Vertex& v2 = m.vertex_source[k2]; Vector normal = cross( v1.position - v0.position, v2.position - v0.position); v0.normal += normal; v1.normal += normal; v2.normal += normal; } } // 法線後処理 for (Piece& m: pieces_) { for (auto& v: m.vertex_source) { normalize_f(v.normal); } } build_pieces(); }