📄 model.cpp
字号:
break; default: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // default blend func } if (nozwrite) { glDepthMask(GL_TRUE); } if (texanim!=-1) {
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
if (unlit) {
glEnable(GL_LIGHTING); //if (gWorld && gWorld->drawfog) glEnable(GL_FOG); } if (useenvmap) { glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
} if (swrap) { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); } if (twrap) { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); } /*
if (usetex2) {
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0);
}
*/
//glColor4f(1,1,1,1); //???}void Model::drawModel(){ // assume these client states are enabled: GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_TEXTURE_COORD_ARRAY if (supportVBO) { if (animated) { if (animGeometry) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbuf); glVertexPointer(3, GL_FLOAT, 0, 0); glNormalPointer(GL_FLOAT, 0, GL_BUFFER_OFFSET(vbufsize)); } else { glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbuf); glVertexPointer(3, GL_FLOAT, 0, 0); glBindBufferARB(GL_ARRAY_BUFFER_ARB, nbuf); glNormalPointer(GL_FLOAT, 0, 0); } glBindBufferARB(GL_ARRAY_BUFFER_ARB, tbuf); glTexCoordPointer(2, GL_FLOAT, 0, 0); //glTexCoordPointer(2, GL_FLOAT, sizeof(ModelVertex), &origVertices[0].texcoords); } } else { if (animated) { glVertexPointer(3, GL_FLOAT, 0, vertices);
glNormalPointer(GL_FLOAT, 0, normals); glTexCoordPointer(2, GL_FLOAT, 0, texcoords); } } // Not needed? glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glAlphaFunc (GL_GREATER, 0.5f); for (size_t i=0; i<passes.size(); i++) { ModelRenderPass &p = passes[i]; if (p.init(this)) { // we don't want to render completely transparent parts
// render
if (animated) {
//glDrawElements(GL_TRIANGLES, p.indexCount, GL_UNSIGNED_SHORT, indices + p.indexStart);
// a GDC OpenGL Performace Tuning paper recommended glDrawRangeElements over glDrawElements
// I can't notice a difference but I guess it can't hurt
if (supportVBO && supportDrawRangeElements) {
glDrawRangeElements(GL_TRIANGLES, p.vertexStart, p.vertexEnd, p.indexCount, GL_UNSIGNED_SHORT, indices + p.indexStart);
} else {
glDrawElements(GL_TRIANGLES, p.indexCount, GL_UNSIGNED_SHORT, indices + p.indexStart);
}
} else {
glBegin(GL_TRIANGLES);
for (size_t k = 0, b=p.indexStart; k<p.indexCount; k++,b++) {
uint16 a = indices[b];
glNormal3fv(normals[a]);
glTexCoord2fv(origVertices[a].texcoords);
glVertex3fv(vertices[a]);
}
glEnd();
}
}
p.deinit();
} // done with all render ops /* // Is all this really needed ? glAlphaFunc(GL_GREATER, 0.0f); glDisable(GL_ALPHA_TEST); GLfloat czero[4] = {0.0f, 0.0f, 0.0f, 1.0f}; glMaterialfv(GL_FRONT, GL_EMISSION, czero);
//glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
//glDepthMask(GL_TRUE); */}void TextureAnim::calc(int anim, int time)
{
if (trans.used) {
tval = trans.getValue(anim, time);
}
if (rot.used) {
rval = rot.getValue(anim, time);
}
if (scale.used) {
sval = scale.getValue(anim, time);
}
}
void TextureAnim::setup()
{
glLoadIdentity();
if (trans.used) {
glTranslatef(tval.x, tval.y, tval.z);
}
if (rot.used) {
glRotatef(rval.x, 0, 0, 1); // this is wrong, I have no idea what I'm doing here ;)
}
if (scale.used) {
glScalef(sval.x, sval.y, sval.z);
}
}
void ModelCamera::init(MPQFile &f, ModelCameraDef &mcd, int *global)
{
ok = true;
nearclip = mcd.nearclip;
farclip = mcd.farclip;
fov = mcd.fov;
pos = fixCoordSystem(mcd.pos);
target = fixCoordSystem(mcd.target);
tPos.init(mcd.transPos, f, global);
tTarget.init(mcd.transTarget, f, global);
rot.init(mcd.rot, f, global);
tPos.fix(fixCoordSystem);
tTarget.fix(fixCoordSystem);
}
void ModelCamera::setup(int time)
{
if (!ok) return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); gluPerspective(fov * 34.5f, (GLfloat)gXres/(GLfloat)gYres, nearclip, farclip);
Vec3D p = pos + tPos.getValue(0, time);
Vec3D t = target + tTarget.getValue(0, time);
Vec3D u(0,1,0);
float roll = rot.getValue(0, time) / PI * 180.0f;
glMatrixMode(GL_MODELVIEW); glLoadIdentity();
gluLookAt(p.x, p.y, p.z, t.x, t.y, t.z, u.x, u.y, u.z);
//glRotatef(roll, 0, 0, 1);
}
void ModelColor::init(MPQFile &f, ModelColorDef &mcd, int *global)
{
color.init(mcd.color, f, global);
opacity.init(mcd.opacity, f, global);
}
void ModelTransparency::init(MPQFile &f, ModelTransDef &mcd, int *global)
{
trans.init(mcd.trans, f, global);
}
void ModelLight::init(MPQFile &f, ModelLightDef &mld, int *global)
{
tpos = pos = fixCoordSystem(mld.pos);
tdir = dir = Vec3D(0,1,0); // no idea
type = mld.type;
parent = mld.bone;
ambColor.init(mld.ambColor, f, global);
ambIntensity.init(mld.ambIntensity, f, global);
diffColor.init(mld.color, f, global);
diffIntensity.init(mld.intensity, f, global);
}
void ModelLight::setup(int time, GLuint l)
{
Vec4D ambcol(ambColor.getValue(0, time) * ambIntensity.getValue(0, time), 1.0f);
Vec4D diffcol(diffColor.getValue(0, time) * diffIntensity.getValue(0, time), 1.0f);
Vec4D p;
if (type==0) {
// directional
p = Vec4D(tdir, 0.0f);
} else {
// point
p = Vec4D(tpos, 1.0f);
}
//gLog("Light %d (%f,%f,%f) (%f,%f,%f) [%f,%f,%f]\n", l-GL_LIGHT4, ambcol.x, ambcol.y, ambcol.z, diffcol.x, diffcol.y, diffcol.z, p.x, p.y, p.z);
glLightfv(l, GL_POSITION, p);
glLightfv(l, GL_DIFFUSE, diffcol);
glLightfv(l, GL_AMBIENT, ambcol);
glEnable(l);
}
void TextureAnim::init(MPQFile &f, ModelTexAnimDef &mta, int *global)
{
trans.init(mta.trans, f, global);
rot.init(mta.rot, f, global);
scale.init(mta.scale, f, global);
}
void Bone::init(MPQFile &f, ModelBoneDef &b, int *global){ parent = b.parent; pivot = fixCoordSystem(b.pivot); billboard = (b.flags & 8) != 0; trans.init(b.translation, f, global);
rot.init(b.rotation, f, global);
scale.init(b.scaling, f, global);
trans.fix(fixCoordSystem);
rot.fix(fixCoordSystemQuat);
scale.fix(fixCoordSystem2);
}void ModelAttachment::init(MPQFile &f, ModelAttachmentDef &mad, int *global)
{
pos = fixCoordSystem(mad.pos);
bone = mad.bone;
id = mad.id;
}
void ModelAttachment::setup()
{
Matrix m = model->bones[bone].mat;
m.transpose();
glMultMatrixf(m);
glTranslatef(pos.x, pos.y, pos.z);
}
void ModelAttachment::setupParticle()
{
/*
Matrix m = model->bones[bone].mat;
m.transpose();
glMultMatrixf(m);
glTranslatef(pos.x, pos.y, pos.z);
*/
}
void Bone::calcMatrix(Bone *allbones, int anim, int time){ if (calc) return; Matrix m; Quaternion q; bool tr = rot.used || scale.used || trans.used || billboard; if (tr) { m.translation(pivot); if (trans.used) { Vec3D tr = trans.getValue(anim, time); m *= Matrix::newTranslation(tr); } if (rot.used) { q = rot.getValue(anim, time); m *= Matrix::newQuatRotate(q); } if (scale.used) { Vec3D sc = scale.getValue(anim, time); m *= Matrix::newScale(sc); } if (billboard) { Matrix mtrans; glGetFloatv(GL_MODELVIEW_MATRIX, &(mtrans.m[0][0])); mtrans.transpose(); mtrans.invert(); Vec3D camera = mtrans * Vec3D(0,0,0); Vec3D look = (camera - pivot).normalize(); //Vec3D up(0,1,0); Vec3D up = ((mtrans * Vec3D(0,1,0)) - camera).normalize(); // these should be normalized by default but fp inaccuracy kicks in when looking down :( Vec3D right = (up % look).normalize(); up = (look % right).normalize(); // calculate a billboard matrix Matrix mbb; mbb.unit(); //* mbb.m[0][2] = right.x; mbb.m[1][2] = right.y; mbb.m[2][2] = right.z; mbb.m[0][1] = up.x; mbb.m[1][1] = up.y; mbb.m[2][1] = up.z; mbb.m[0][0] = look.x; mbb.m[1][0] = look.y; mbb.m[2][0] = look.z; /*/ // the above version seems to be correct, but at this point I really have no idea :| mbb.m[0][1] = right.x; mbb.m[1][1] = right.y; mbb.m[2][1] = right.z; mbb.m[0][2] = up.x; mbb.m[1][2] = up.y; mbb.m[2][2] = up.z; mbb.m[0][0] = look.x; mbb.m[1][0] = look.y; mbb.m[2][0] = look.z; //*/ m *= mbb; } m *= Matrix::newTranslation(pivot*-1.0f); } else m.unit(); if (parent>=0) { allbones[parent].calcMatrix(allbones, anim, time); mat = allbones[parent].mat * m; } else mat = m; // transform matrix for normal vectors ... ?? if (rot.used) { if (parent>=0) { mrot = allbones[parent].mrot * Matrix::newQuatRotate(q); } else mrot = Matrix::newQuatRotate(q); } else mrot.unit(); transPivot = mat * pivot; calc = true;}void Model::draw(){ if (!ok) return; //glEnable(GL_TEXTURE_2D); if (!animated) { glCallList(dlist); } else { if (ind) animate(currentAnim); else { if (!animcalc) { animate(currentAnim); animcalc = true; } } lightsOn(GL_LIGHT4); drawModel(); lightsOff(GL_LIGHT4);
}}void Model::lightsOn(GLuint lbase)
{
// setup lights for (unsigned int i=0, l=lbase; i<header.nLights; i++) lights[i].setup(animtime, l++);
}
void Model::lightsOff(GLuint lbase)
{
for (unsigned int i=0, l=lbase; i<header.nLights; i++) glDisable(l++);
}
void Model::updateEmitters(float dt)
{
if (!ok)
return;
for (size_t i=0; i<header.nParticleEmitters; i++) {
particleSystems[i].update(dt);
}
}
void Model::drawBones()
{
glDisable(GL_DEPTH_TEST);
glBegin(GL_LINES);
for (size_t i=0; i<header.nBones; i++) {
//for (size_t i=30; i<40; i++) {
if (bones[i].parent != -1) {
glVertex3fv(bones[i].transPivot);
glVertex3fv(bones[bones[i].parent].transPivot);
}
}
glEnd();
glEnable(GL_DEPTH_TEST);
}
void Model::setupAtt(int id)
{
int l = attLookup[id];
if (l>=0)
atts[l].setup();
}
void Model::drawBoundingVolume()
{ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glBegin(GL_TRIANGLES); for (size_t i=0; i<header.nBoundingTriangles; i++) {
size_t v = boundTris[i];
if (v < header.nBoundingVertices)
glVertex3fv(bounds[v]);
else
glVertex3f(0,0,0);
}
glEnd(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);}void Model::drawParticles()
{ // draw particle systems for (size_t i=0; i<header.nParticleEmitters; i++) {
particleSystems[i].draw();
} // draw ribbons for (size_t i=0; i<header.nRibbonEmitters; i++) {
ribbons[i].draw();
}}int ModelManager::add(std::string name){ int id; if (names.find(name) != names.end()) { id = names[name]; items[id]->addref(); return id; } // load new Model *model = new Model(name); id = nextID(); do_add(name, id, model); return id;}void ModelManager::resetAnim(){ for (std::map<int, ManagedItem*>::iterator it = items.begin(); it != items.end(); ++it) { ((Model*)it->second)->animcalc = false; }}void ModelManager::updateEmitters(float dt){ for (std::map<int, ManagedItem*>::iterator it = items.begin(); it != items.end(); ++it) { ((Model*)it->second)->updateEmitters(dt); }}void ModelManager::clear()
{
for (std::map<int, ManagedItem*>::iterator it = items.begin(); it != items.end(); ++it) { doDelete(it->first); delete it->second; } items.clear(); names.clear();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -