|
ORTS
|
00001 // $Id: GfxAnimesh.C 7357 2008-08-07 02:38:57Z furtak $ 00002 00003 // This is an ORTS file (c) Keith Yerex, licensed under the GPL 00004 00005 #include "GfxGlobal.H" 00006 #include "GameStateModule.H" 00007 #include "GfxAnimesh.H" 00008 #include "GfxModule.H" 00009 #include "CycleCounter.H" 00010 #include "GameObj.H" 00011 #include "Image.H" 00012 #include "Game.H" 00013 #include "MD2.H" 00014 #include "MD3.H" 00015 #include "Profiler.H" 00016 00017 #include "GfxEmitter.H" 00018 00019 #ifndef GCC 00020 static sint4 round(real8 x) { return (sint4)floor(x+0.5); } 00021 #endif 00022 00023 using namespace std; 00024 00025 //=================================================================== 00026 00027 map<string, Model::TexPair> Model::textures; 00028 Vector<Vec4<real4> > Model::colors; 00029 00030 map<string, Model*> GfxAnimesh::name2mdl; 00031 map<string, CustomShaderProgram*> GfxAnimesh::name2shader; // modelfile -> shader 00032 CustomShaderProgram* GfxAnimesh::default_shader = 0; 00033 real4 GfxAnimesh::gamma = 1.0; // gamma correct all model textures by this value 00034 sint4 GfxAnimesh::mode = 0; 00035 sint4 GfxAnimesh::texmode = 2; 00036 sint4 GfxAnimesh::texlevel = 0; 00037 GLuint GfxAnimesh::default_shadow_tex = 0; 00038 00039 bool Model::clear_fast = false; 00040 bool Model::verbose_load = false; 00041 00042 //=================================================================== 00043 00044 GfxAnimesh::GfxAnimesh(GfxModule &g, const std::string &modelfile, const std::string &texfile, 00045 sint4 team, real4 scale, real4 dy) 00046 { 00047 set_gfxm(g); 00048 shadow_tex = default_shadow_tex; 00049 shadow_on = 0; 00050 shadow_sc = 0.0; 00051 00052 mdl = 0; 00053 shader = 0; 00054 00055 load(modelfile, texfile, team, scale, dy); 00056 } 00057 00058 //=================================================================== 00059 00060 void GfxAnimesh::load(const string &modelfile, const string &texfile, sint4 team_, 00061 real4 scale_, real4 dy) 00062 { 00063 PROFILE("GfxAnimesh::load"); 00064 00065 team = team_; 00066 map<string, Model*>::const_iterator it; 00067 00068 if ((it = name2mdl.find(modelfile)) != name2mdl.end()) mdl = it->second; 00069 else { 00070 00071 string ext; 00072 size_t p = modelfile.rfind("."); 00073 if (p != string::npos) { 00074 ext = modelfile.substr(p+1); 00075 } 00076 00077 if (ext == "md3") { 00078 switch(mode) { 00079 case 1: mdl = new MD3_Model; break; 00080 //case 2: mdl = new MD3_Model_VB; break; 00081 default: mdl = new MD3_Model_DL; break; 00082 } 00083 00084 } else if (ext == "md2"){ 00085 switch(mode) { 00086 case 1: mdl = new MD2_Model; break; 00087 case 2: mdl = new MD2_Model_VB; break; 00088 default: mdl = new MD2_Model_DL; break; 00089 } 00090 } else { 00091 ERR2("unknown extension:", modelfile.c_str()); 00092 } 00093 mdl->load(modelfile, texfile, 100.0, dy, gamma); 00094 name2mdl[modelfile] = mdl; 00095 00096 CustomShaderProgram *csp = new CustomShaderProgram; 00097 if (csp->load(modelfile + ".custom")) { 00098 name2shader[modelfile] = csp; 00099 } else { 00100 ShaderProgram *sp = new ShaderProgram(); 00101 sp->vertex_shader(modelfile + ".vert"); 00102 sp->fragment_shader(modelfile + ".frag"); 00103 if (sp->id()) { 00104 csp->load(sp); 00105 name2shader[modelfile] = csp; 00106 } else { 00107 delete sp; 00108 delete csp; 00109 } 00110 } 00111 } 00112 00113 { 00114 FIND (name2shader, it2, modelfile); 00115 if (it2 != name2shader.end()) shader = it2->second; 00116 } 00117 00118 centroid = mdl->centroid; 00119 radius = mdl->radius; 00120 set_scale(scale_ * 0.01); 00121 00122 idle.frame = 0; 00123 idle.first = 0; 00124 idle.loop_first = 0; 00125 idle.last = 0; 00126 idle.fps = 0; 00127 idle.mode = FrameSet::REPEAT; 00128 idle.f1 = 0; 00129 idle.f2 = 0; 00130 idle.blend = 0.0; 00131 00132 current.frame = 0; 00133 current.first = 0; 00134 current.loop_first = 0; 00135 current.last = 0; 00136 current.fps = 0; 00137 current.mode = FrameSet::STOP; 00138 current.f1 = 0; 00139 current.f2 = 0; 00140 current.blend = 0.0; 00141 } 00142 00143 //=================================================================== 00144 00145 GfxAnimesh::~GfxAnimesh() 00146 { 00147 } 00148 00149 //=================================================================== 00150 00151 void GfxAnimesh::update(real4 dt) 00152 { 00153 PROFILE("GfxAnimesh::update"); 00154 00155 if (!current.update(dt)) current = idle; 00156 00157 assert(mdl); 00158 if (current.f1 >= (sint4)mdl->bbox.size()) return; 00159 00160 aabb_o = pose.center + mdl->bbox[current.f1].min * pose.scale; 00161 aabb_d = (mdl->bbox[current.f1].max - mdl->bbox[current.f1].min) * pose.scale; 00162 00163 FORALL (sub_objects, it) (*it)->update(dt); 00164 FORALL (emitters, it) (*it)->update(dt); 00165 00166 FORALL (sub_objects_tag, it) (*it).obj->update(dt); 00167 FORALL (emitters_tag, it) (*it).obj->update(dt); 00168 } 00169 00170 //=================================================================== 00171 00172 void GfxAnimesh::beginDraw() 00173 { 00174 glEnable(GL_BLEND); 00175 glDisable(GL_LIGHTING); 00176 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00177 00178 if (glBlendEquationEXT) { 00179 glBlendEquationEXT(GL_FUNC_ADD_EXT); 00180 } else { 00181 glBlendEquation(GL_FUNC_ADD); 00182 } 00183 00184 glCullFace(GL_FRONT); 00185 00186 glActiveTextureARB(GL_TEXTURE0); 00187 glEnable(GL_TEXTURE_2D); 00188 glColor4f(1, 1, 1, 1); 00189 } 00190 00191 //------------------------------------------------------------------- 00192 00193 void GfxAnimesh::endDraw() 00194 { 00195 glDisable(GL_BLEND); 00196 glActiveTextureARB(GL_TEXTURE0); 00197 glDisable(GL_TEXTURE_2D); 00198 00199 glCullFace(GL_BACK); 00200 00201 glDisable(GL_LIGHTING); 00202 } 00203 00204 //=================================================================== 00205 00206 void GfxAnimesh::draw() 00207 { 00208 PROFILE("GfxAnimesh::draw"); 00209 00210 glerror("GfxAnimesh::draw 0"); 00211 glLoadName(my_id << GfxObject::SUB_ID_LOG); 00212 00213 glPushMatrix(); 00214 apply_pose(); 00215 00216 CustomShaderProgram *prog; 00217 if (shader) { 00218 prog = shader; 00219 } else { 00220 prog = default_shader; 00221 } 00222 00223 if (prog) { 00224 00225 glActiveTextureARB(GL_TEXTURE2); 00226 glBindTexture(GL_TEXTURE_2D, mdl->tex->team_tex); 00227 glActiveTextureARB(GL_TEXTURE0); 00228 glBindTexture(GL_TEXTURE_2D, mdl->tex->base_tex); 00229 glColor4fv(mdl->get_color(team).ptr()); 00230 00231 FORT (i, prog->num_passes()) { 00232 ShaderProgram *sp = prog->get_pass(i).prog; 00233 if (!sp || !sp->begin()) continue; 00234 prog->get_pass(i).setup(); 00235 00236 GLint tex = glGetUniformLocation(sp->id(), "tex"); 00237 // cout << "tex = " << tex << endl; 00238 if (tex >= 0) glUniform1i(tex, 0); 00239 00240 GLint shadow = glGetUniformLocation(sp->id(), "shadow"); 00241 if (shadow >= 0) glUniform1i(shadow, 1); 00242 00243 GLint team = glGetUniformLocation(sp->id(), "team"); 00244 if (team >= 0) glUniform1i(team, 2); 00245 00246 GLint ntex = glGetUniformLocation(sp->id(), "ntex"); 00247 if (ntex >= 0) glUniform1i(ntex, 3); 00248 00249 mdl->draw(current.f1); 00250 00251 sp->end(); 00252 } 00253 00254 } else { 00255 00256 if (current.first == current.last) { 00257 mdl->draw(current.first, team); 00258 } else { 00259 mdl->draw_interp(current.f1, current.f2, current.blend, team); 00260 } 00261 00262 } 00263 00264 FORALL (sub_objects, it) (*it)->draw(); 00265 00266 FORALL (sub_objects_tag, it) { 00267 GfxObject *o = (*it).obj; 00268 sint4 tag_num = (*it).tag_num; 00269 Mat4<real4> &mat = mdl->tag[tag_num][current.f1].axis; 00270 o->draw_at(mat); 00271 } 00272 00273 glPopMatrix(); 00274 glerror("GfxAnimesh::draw 1"); 00275 } 00276 00277 //=================================================================== 00278 00279 void GfxAnimesh::draw_emitters() 00280 { 00281 PROFILE("GfxAnimesh::draw_emitters"); 00282 00283 glerror("GfxObject::draw_emitters 0"); 00284 00285 glPushMatrix(); 00286 apply_pose(); 00287 00288 FORALL (emitters, i) (*i)->draw_emitters(); 00289 00290 // glScalef(pose.scale, pose.scale, pose.scale); 00291 00292 FORALL (sub_objects, i) (*i)->draw_emitters(); 00293 00294 FORALL (sub_objects_tag, it) { 00295 GfxObject *o = (*it).obj; 00296 sint4 tag_num = (*it).tag_num; 00297 Mat4<real4> &mat = mdl->tag[tag_num][current.f1].axis; 00298 o->draw_emitters_at(mat); 00299 } 00300 00301 FORALL (emitters_tag, it) { 00302 GfxObject *o = (*it).obj; 00303 sint4 tag_num = (*it).tag_num; 00304 Mat4<real4> &mat = mdl->tag[tag_num][current.f1].axis; 00305 o->draw_emitters_at(mat); 00306 } 00307 00308 glPopMatrix(); 00309 glerror("GfxObject::draw_emitters 1"); 00310 } 00311 00312 //=================================================================== 00313 00314 void GfxAnimesh::pick() 00315 { 00316 glerror("GfxAnimesh::pick 0"); 00317 glCullFace(GL_FRONT); 00318 glLoadName(my_id << GfxObject::SUB_ID_LOG); 00319 00320 glPushMatrix(); 00321 apply_pose(); 00322 00323 mdl->select(current.f1); 00324 00325 FORALL (sub_objects, it) (*it)->pick(); 00326 00327 FORALL (sub_objects_tag, it) { 00328 GfxObject *o = (*it).obj; 00329 sint4 tag_num = (*it).tag_num; 00330 Mat4<real4> &mat = mdl->tag[tag_num][current.f1].axis; 00331 00332 glPushMatrix(); 00333 glMultMatrixf(mat.ptr()); 00334 o->pick(); 00335 glPopMatrix(); 00336 } 00337 00338 glPopMatrix(); 00339 glCullFace(GL_BACK); 00340 glerror("GfxAnimesh::pick 1"); 00341 } 00342 00343 //=================================================================== 00344 00345 void GfxAnimesh::draw_shadow() 00346 { 00347 PROFILE("GfxAnimesh::draw_shadow"); 00348 00349 if (!shadow_on) return; 00350 glerror("GfxAnimesh::drawshadow 0"); 00351 glPushMatrix(); 00352 apply_pose(); 00353 00354 if (shadow_tex > 0) { 00355 00356 glColor4f(1, 1, 1, 1); 00357 glActiveTextureARB(GL_TEXTURE0); 00358 glEnable(GL_TEXTURE_2D); 00359 glBindTexture(GL_TEXTURE_2D, shadow_tex); 00360 mdl->draw_shadow(current.f1, shadow_sc); 00361 00362 } else { 00363 00364 glColor4f(0, 0, 0, 0.5); 00365 glActiveTextureARB(GL_TEXTURE1); 00366 glDisable(GL_TEXTURE_2D); 00367 glActiveTextureARB(GL_TEXTURE0); 00368 glDisable(GL_TEXTURE_2D); 00369 00370 mdl->draw(current.f1); 00371 } 00372 00373 FORALL (sub_objects, it) (*it)->draw_shadow(); 00374 00375 FORALL (sub_objects_tag, it) { 00376 GfxObject *o = (*it).obj; 00377 sint4 tag_num = (*it).tag_num; 00378 Mat4<real4> &mat = mdl->tag[tag_num][current.f1].axis; 00379 00380 glPushMatrix(); 00381 glMultMatrixf(mat.ptr()); 00382 o->draw_shadow(); 00383 glPopMatrix(); 00384 } 00385 00386 00387 glPopMatrix(); 00388 glerror("GfxAnimesh::drawshadow"); 00389 } 00390 00391 //=================================================================== 00392 00393 void GfxAnimesh::draw_bbox() 00394 { 00395 glDisable(GL_TEXTURE_2D); 00396 glDisable(GL_CULL_FACE); 00397 glDisable(GL_BLEND); 00398 00399 real4 x0 = aabb_o.x; 00400 real4 x1 = aabb_o.x + aabb_d.x; 00401 real4 y0 = aabb_o.y; 00402 real4 y1 = aabb_o.y + aabb_d.y; 00403 real4 z0 = aabb_o.z; 00404 real4 z1 = aabb_o.z + aabb_d.z; 00405 00406 glColor4f(1,1,1,1); 00407 glBegin(GL_LINES); 00408 glVertex3f(x0, y0, z0); 00409 glVertex3f(x0, y0, z1); 00410 glVertex3f(x0, y1, z0); 00411 glVertex3f(x0, y1, z1); 00412 glVertex3f(x1, y0, z0); 00413 glVertex3f(x1, y0, z1); 00414 glVertex3f(x1, y1, z0); 00415 glVertex3f(x1, y1, z1); 00416 00417 glVertex3f(x0, y0, z0); 00418 glVertex3f(x0, y1, z0); 00419 glVertex3f(x0, y0, z1); 00420 glVertex3f(x0, y1, z1); 00421 glVertex3f(x1, y0, z0); 00422 glVertex3f(x1, y1, z0); 00423 glVertex3f(x1, y0, z1); 00424 glVertex3f(x1, y1, z1); 00425 00426 glVertex3f(x0, y0, z0); 00427 glVertex3f(x1, y0, z0); 00428 glVertex3f(x0, y0, z1); 00429 glVertex3f(x1, y0, z1); 00430 glVertex3f(x0, y1, z0); 00431 glVertex3f(x1, y1, z0); 00432 glVertex3f(x0, y1, z1); 00433 glVertex3f(x1, y1, z1); 00434 00435 glEnd(); 00436 } 00437 00438 //=================================================================== 00439 00440 void GfxAnimesh::play(const string &name, real4 fps, sint2 mode, sint2 looping) 00441 { 00442 pair<sint2,sint2> p = mdl->name2frames[name]; 00443 play(p.first, p.second, fps, mode, looping); 00444 } 00445 00446 //------------------------------------------------------------------- 00447 00448 void GfxAnimesh::play(sint2 start, sint2 end, real4 fps, sint2 mode, sint2 looping) 00449 { 00450 current.fps = fps; 00451 current.mode = mode; 00452 current.first = start; 00453 if (looping >= 0 && looping < (end-start+1)) 00454 current.loop_first = end - looping + 1; 00455 else 00456 current.loop_first = start; 00457 current.last = end; 00458 current.is_custom = false; 00459 if (fps >= 0) { 00460 current.frame = static_cast<real4>(current.first); 00461 current.f1 = current.f2 = current.first; 00462 } else { 00463 current.frame = static_cast<real4>(current.last) + 0.99; 00464 current.f1 = current.f2 = current.last; 00465 } 00466 } 00467 00468 //------------------------------------------------------------------- 00469 00470 void GfxAnimesh::play_custom(const Vector<sint4> &f, real4 fps, sint2 mode) 00471 { 00472 current.fps = fps; 00473 current.mode = mode; 00474 current.set_custom(f); 00475 } 00476 00477 //=================================================================== 00478 00479 void GfxAnimesh::set_idle(const string &name, real4 fps, sint2 mode, sint2 looping) 00480 { 00481 pair<sint2,sint2> p = mdl->name2frames[name]; 00482 00483 idle.fps = fps; 00484 idle.mode = mode; 00485 idle.first = p.first; 00486 idle.last = p.second; 00487 if (looping >= 0 && looping < (idle.last - idle.first + 1)) 00488 idle.loop_first = idle.last - looping + 1; 00489 else 00490 idle.loop_first = idle.first; 00491 idle.is_custom = false; 00492 if (fps >= 0) { 00493 idle.frame = static_cast<real4>(idle.first); 00494 idle.f1 = idle.f2 = idle.first; 00495 } else { 00496 idle.frame = static_cast<real4>(idle.last) + 0.99; 00497 idle.f1 = idle.f2 = idle.last; 00498 } 00499 } 00500 00501 //=================================================================== 00502 00503 void GfxAnimesh::set_frame(const string &name, sint2 frame) 00504 { 00505 pair<sint2,sint2> p = mdl->name2frames[name]; 00506 00507 current.mode = FrameSet::HALT; 00508 current.fps = 0; 00509 current.f1 = frame + p.first; 00510 current.f2 = frame + p.first; 00511 current.blend = 0.0; 00512 current.frame = static_cast<real4>(frame + p.first); 00513 current.first = p.first; 00514 current.last = p.second; 00515 } 00516 00517 //=================================================================== 00518 00519 void GfxAnimesh::attachGfxObject_tag(GfxObject *go, const string &tag) 00520 { 00521 if (!mdl) { 00522 cout << "no model" << endl; 00523 return; 00524 } 00525 00526 sint4 tag_id = -1; 00527 FORALL (mdl->tag_name, i) { 00528 if (*i == tag) { 00529 tag_id = i-mdl->tag_name.begin(); 00530 break; 00531 } 00532 } 00533 if (tag_id == -1) { 00534 cout << "no such tag" << endl; 00535 return; 00536 } 00537 00538 GfxTag gt; 00539 gt.obj = go; 00540 gt.tag_num = tag_id; 00541 00542 sub_objects_tag.push_back(gt); 00543 } 00544 00545 //------------------------------------------------------------------- 00546 00547 void GfxAnimesh::attachEmitter_tag(GfxObject *go, const string &tag) 00548 { 00549 if (!mdl) return; 00550 00551 sint4 tag_id = -1; 00552 FORALL (mdl->tag_name, i) { 00553 if (*i == tag) { 00554 tag_id = i - mdl->tag_name.begin(); 00555 break; 00556 } 00557 } 00558 if (tag_id == -1) return; 00559 00560 GfxTag gt; 00561 gt.obj = go; 00562 gt.tag_num = tag_id; 00563 00564 emitters_tag.push_back(gt); 00565 } 00566 00567 //=================================================================== 00568 00569 Model::~Model() 00570 { 00571 delete [] all_tags; 00572 } 00573 00574 //------------------------------------------------------------------- 00575 00576 sint4 Model::load_textures(const string &filename, real4 gamma) 00577 { 00578 PROFILE("Model::load_textures"); 00579 00580 TexPair &tp = textures[filename]; 00581 tex = &tp; 00582 if (tp.base_tex) return 1; // already loaded 00583 00584 // Mesh texture 00585 string fileTex = filename + ".tga"; 00586 Image imgTex(fileTex.c_str(), gamma); 00587 00588 // Team colour texture 00589 string fileTeam = filename + "_color.tga"; 00590 Image imgTeam(fileTeam.c_str(), gamma); 00591 uint1 *color_data = imgTeam.pixels(); 00592 00593 GLuint type; 00594 00595 switch (imgTex.bpp()) { 00596 case 1: type = GL_LUMINANCE; break; 00597 case 3: type = GL_RGB; break; 00598 case 4: type = GL_RGBA; break; 00599 default: ERR("bpp not handled"); 00600 } 00601 00602 //---------------------------------------- 00603 tp.base_tex=imgTex.createTexture(static_cast<Image::FILTER>(GfxAnimesh::get_texmode()), 00604 GfxAnimesh::get_texlevel()); 00605 00606 if (imgTeam.bpp() == 1) { // no alpha for the team color map 00607 Image aTeam; 00608 aTeam.empty(imgTeam.width(), imgTeam.height(), 2); // with alpha 00609 uint1 *adata = aTeam.pixels(); 00610 00611 FORU (i, imgTeam.width() * imgTeam.height()) { 00612 uint1 l = color_data[i]; 00613 adata[i*2] = l; 00614 adata[i*2+1] = l ? 255 : 0; 00615 } 00616 00617 tp.team_tex=aTeam.createTexture(static_cast<Image::FILTER>(GfxAnimesh::get_texmode()), 00618 GfxAnimesh::get_texlevel()); 00619 00620 } else if (imgTeam.bpp() == 2) { 00621 tp.team_tex=imgTeam.createTexture(static_cast<Image::FILTER>(GfxAnimesh::get_texmode()), 00622 GfxAnimesh::get_texlevel()); 00623 } else { 00624 ERR("invalid color map bpp"); 00625 } 00626 //---------------------------------------- 00627 00628 return 1; 00629 } 00630 00631 //=================================================================== 00632 00633 void FrameSet::set_custom(const Vector<sint4> &v) 00634 { 00635 frame = 0; 00636 first = 0; 00637 loop_first = 0; 00638 last = v.size() - 1; 00639 00640 is_custom = true; 00641 custom.clear(); 00642 FORALL (v, i) custom.push_back(*i); 00643 custom.push_back(custom[0]); 00644 00645 f1 = custom[0]; 00646 f2 = custom[1]; 00647 blend = 0.0; 00648 } 00649 00650 //------------------------------------------------------------------- 00651 00652 bool FrameSet::update(real4 dt) 00653 { 00654 frame += dt * fps; 00655 00656 if (frame >= last+1.0 || frame < first) { 00657 00658 switch (mode) { 00659 00660 case FrameSet::STOP: 00661 return false; 00662 00663 case FrameSet::REPEAT: 00664 first = loop_first; 00665 if (first == last) frame = first; 00666 else { 00667 if (fps > 0) 00668 do { 00669 frame -= (last-first+1); 00670 } while (frame >= last+1.0); 00671 else 00672 do { 00673 frame += (last-first+1); 00674 } while (frame < first); 00675 } 00676 break; 00677 00678 case FrameSet::MIRROR: 00679 fps *= -1; 00680 frame += dt*fps; 00681 break; 00682 00683 case FrameSet::HALT: 00684 if (fps > 0) { 00685 frame = last; 00686 } else if (fps < 0) { 00687 frame = first; 00688 } 00689 fps = 0; 00690 break; 00691 } 00692 } 00693 00694 if (fps == 0) { 00695 00696 f1 = f2 = static_cast<sint2>(frame); 00697 blend = 0; 00698 00699 } else if (fps > 0) { 00700 00701 sint4 f = static_cast<sint4>(floor(frame)); 00702 f1 = f; 00703 f2 = f+1; 00704 if (f2 > last) { 00705 if (mode == FrameSet::REPEAT) { 00706 f2 = first; 00707 } else { 00708 f2 = last; 00709 } 00710 } 00711 blend = frame - f; 00712 00713 } else { 00714 00715 // sint4 f = (sint4)ceil(frame); 00716 sint4 f = static_cast<sint4>(floor(frame)); 00717 f1 = f; 00718 f2 = f-1; 00719 if (f2 < first) { 00720 if (mode == FrameSet::REPEAT) { 00721 f2 = last; 00722 } else { 00723 f2 = first; 00724 } 00725 } 00726 blend = f - frame; 00727 00728 } 00729 00730 if (is_custom) { 00731 f1 = custom[f1]; 00732 f2 = custom[f2]; 00733 } 00734 00735 return true; 00736 } 00737 00738 //===================================================================