📄 model.cpp
字号:
textures[i] = texturemanager.add(texname); } else { // special texture - only on characters and such... textures[i] = 0; //while (texdef[i].type < 16 && specialTextures[texdef[i].type]!=-1) texdef[i].type++; //if (texdef[i].type < 16)specialTextures[texdef[i].type] = (int)i; specialTextures[i] = texdef[i].type; useReplaceTextures[texdef[i].type] = true; } } } /* // replacable textures - it seems to be better to get this info from the texture types if (header.nTexReplace) { size_t m = header.nTexReplace; if (m>16) m = 16; int16 *texrep = (int16*)(f.getBuffer() + header.ofsTexReplace); for (size_t i=0; i<m; i++) specialTextures[i] = texrep[i]; } */ // attachments // debug code here if (header.nAttachments) { ModelAttachmentDef *attachments = (ModelAttachmentDef*)(f.getBuffer() + header.ofsAttachments); for (size_t i=0; i<header.nAttachments; i++) { ModelAttachment att; att.model = this; att.init(f, attachments[i], globalSequences); atts.push_back(att); } } if (header.nAttachLookup) { int16 *p = (int16*)(f.getBuffer() + header.ofsAttachLookup); for (size_t i=0; i<header.nAttachLookup; i++) { attLookup[i] = p[i]; } } // init colors if (header.nColors) { colors = new ModelColor[header.nColors]; ModelColorDef *colorDefs = (ModelColorDef*)(f.getBuffer() + header.ofsColors);
for (size_t i=0; i<header.nColors; i++) colors[i].init(f, colorDefs[i], globalSequences); }
// init transparency
int16 *transLookup = (int16*)(f.getBuffer() + header.ofsTransparencyLookup);
if (header.nTransparency) { transparency = new ModelTransparency[header.nTransparency]; ModelTransDef *trDefs = (ModelTransDef*)(f.getBuffer() + header.ofsTransparency);
for (size_t i=0; i<header.nTransparency; i++) transparency[i].init(f, trDefs[i], globalSequences); }
// just use the first LOD/view // indices - allocate space, too ModelView *view = (ModelView*)(f.getBuffer() + header.ofsViews); uint16 *indexLookup = (uint16*)(f.getBuffer() + view->ofsIndex); uint16 *triangles = (uint16*)(f.getBuffer() + view->ofsTris); nIndices = view->nTris; indices = new uint16[nIndices]; for (size_t i = 0; i<nIndices; i++) { indices[i] = indexLookup[triangles[i]]; } // render ops ModelGeoset *ops = (ModelGeoset*)(f.getBuffer() + view->ofsSub); ModelTexUnit *tex = (ModelTexUnit*)(f.getBuffer() + view->ofsTex); ModelRenderFlags *renderFlags = (ModelRenderFlags*)(f.getBuffer() + header.ofsTexFlags);
uint16 *texlookup = (uint16*)(f.getBuffer() + header.ofsTexLookup); uint16 *texanimlookup = (uint16*)(f.getBuffer() + header.ofsTexAnimLookup); int16 *texunitlookup = (int16*)(f.getBuffer() + header.ofsTexUnitLookup); showGeosets = new bool[view->nSub]; for (size_t i=0; i<view->nSub; i++) { geosets.push_back(ops[i]); showGeosets[i] = true; } for (size_t j = 0; j<view->nTex; j++) { ModelRenderPass pass; pass.usetex2 = false; //pass.texture2 = 0; size_t geoset = tex[j].op; pass.geoset = (int)geoset; pass.indexStart = ops[geoset].istart; pass.indexCount = ops[geoset].icount; pass.vertexStart = ops[geoset].vstart; pass.vertexEnd = pass.vertexStart + ops[geoset].vcount; pass.order = tex[j].order; //TextureID texid = textures[texlookup[tex[j].textureid]]; //pass.texture = texid; pass.tex = texlookup[tex[j].textureid]; // TODO: figure out these flags properly -_- ModelRenderFlags &rf = renderFlags[tex[j].flagsIndex]; pass.useenvmap = (texunitlookup[tex[j].texunit] == -1) && (j < 1);
pass.blendmode = rf.blend;
pass.color = tex[j].colorIndex;
pass.opacity = transLookup[tex[j].transid];
pass.cull = (rf.flags & 4)==0 && rf.blend==0;
pass.unlit = (rf.flags & 3)!=0;
pass.nozwrite = pass.blendmode >= 2 || (rf.flags & 16)!=0;
pass.trans = pass.blendmode != 0;
pass.p = ops[geoset].v.x;
pass.swrap = (texdef[pass.tex].flags & 1) != 0;
pass.twrap = (texdef[pass.tex].flags & 2) != 0;
if (animTextures) {
//if (tex[j].flags & 16) {
if (tex[j].flags & 15) {
pass.texanim = -1; // no texture animation
} else {
pass.texanim = texanimlookup[tex[j].texanimid];
}
} else {
pass.texanim = -1; // no texture animation
}
passes.push_back(pass); } // transparent parts come later std::sort(passes.begin(), passes.end()); // zomg done}void Model::initStatic(MPQFile &f){ origVertices = (ModelVertex*)(f.getBuffer() + header.ofsVertices); initCommon(f); dlist = glGenLists(1); glNewList(dlist, GL_COMPILE); drawModel(); glEndList(); // clean up vertices, indices etc delete[] vertices; delete[] normals; delete[] indices; if (colors) delete[] colors; if (transparency) delete[] transparency;}void Model::initAnimated(MPQFile &f){ origVertices = new ModelVertex[header.nVertices]; memcpy(origVertices, f.getBuffer() + header.ofsVertices, header.nVertices * sizeof(ModelVertex)); if (supportVBO) {
glGenBuffersARB(1,&vbuf); glGenBuffersARB(1,&tbuf); } const size_t size = header.nVertices * sizeof(float); vbufsize = 3 * size; // we multiple by 3 for the x, y, z positions of the vertex initCommon(f); if (animBones) { // init bones... bones = new Bone[header.nBones]; ModelBoneDef *mb = (ModelBoneDef*)(f.getBuffer() + header.ofsBones); for (size_t i=0; i<header.nBones; i++) { bones[i].init(f, mb[i], globalSequences); } } if (!animGeometry && supportVBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbuf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, vbufsize, vertices, GL_STATIC_DRAW_ARB); glGenBuffersARB(1,&nbuf); glBindBufferARB(GL_ARRAY_BUFFER_ARB, nbuf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, vbufsize, normals, GL_STATIC_DRAW_ARB); delete[] vertices; delete[] normals; } texcoords = new Vec2D[header.nVertices]; for (size_t i=0; i<header.nVertices; i++) texcoords[i] = origVertices[i].texcoords; // If we're a VBO card, load the texture coord buffer into video memory if (supportVBO) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, tbuf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, 2*size, texcoords, GL_STATIC_DRAW_ARB); delete[] texcoords; } if (animTextures) { texanims = new TextureAnim[header.nTexAnims]; ModelTexAnimDef *ta = (ModelTexAnimDef*)(f.getBuffer() + header.ofsTexAnims); for (size_t i=0; i<header.nTexAnims; i++) { texanims[i].init(f, ta[i], globalSequences); } } // particle systems if (header.nParticleEmitters) { ModelParticleEmitterDef *pdefs = (ModelParticleEmitterDef *)(f.getBuffer() + header.ofsParticleEmitters); particleSystems = new ParticleSystem[header.nParticleEmitters]; hasParticles = true; for (size_t i=0; i<header.nParticleEmitters; i++) { particleSystems[i].model = this; particleSystems[i].init(f, pdefs[i], globalSequences); } } // ribbons if (header.nRibbonEmitters) { ModelRibbonEmitterDef *rdefs = (ModelRibbonEmitterDef *)(f.getBuffer() + header.ofsRibbonEmitters); ribbons = new RibbonEmitter[header.nRibbonEmitters]; for (size_t i=0; i<header.nRibbonEmitters; i++) { ribbons[i].model = this; ribbons[i].init(f, rdefs[i], globalSequences); } } // just use the first camera, meh if (header.nCameras>0) { ModelCameraDef *camDefs = (ModelCameraDef*)(f.getBuffer() + header.ofsCameras); cam.init(f, camDefs[0], globalSequences); hasCamera = true; } // init lights if (header.nLights) { lights = new ModelLight[header.nLights]; ModelLightDef *lDefs = (ModelLightDef*)(f.getBuffer() + header.ofsLights);
for (size_t i=0; i<header.nLights; i++) lights[i].init(f, lDefs[i], globalSequences); }
if (header.nAnimations > 0) { anims = new ModelAnimation[header.nAnimations]; memcpy(anims, f.getBuffer() + header.ofsAnimations, header.nAnimations * sizeof(ModelAnimation)); animManager = new AnimManager(anims); } animcalc = false;}void Model::calcBones(int anim, int time)
{
for (size_t i=0; i<header.nBones; i++) {
bones[i].calc = false;
}
for (size_t i=0; i<header.nBones; i++) {
bones[i].calcMatrix(bones, anim, time);
}
/*
for (size_t i=(header.nBones/2); i<header.nBones; i++) {
bones[i].calcMatrix(bones, anim+1, time);
}*/
}
void Model::animate(int anim){ int t=0; ModelAnimation &a = anims[anim]; int tmax = (a.timeEnd-a.timeStart); if (tmax==0) tmax = 1; if (isWMO == true) { t = globalTime;
t %= tmax;
t += a.timeStart; } else t = animManager->GetFrame(); this->animtime = t; this->anim = anim; if (animBones) { calcBones(anim, t); } if (animGeometry) { if (supportVBO) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbuf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, 2*vbufsize, NULL, GL_STREAM_DRAW_ARB); vertices = (Vec3D*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY); } // transform vertices ModelVertex *ov = origVertices; for (size_t i=0,k=0; i<header.nVertices; ++i,++ov) { Vec3D v(0,0,0), n(0,0,0); for (size_t b=0; b<4; b++) { if (ov->weights[b]>0) { Vec3D tv = bones[ov->bones[b]].mat * ov->pos; Vec3D tn = bones[ov->bones[b]].mrot * ov->normal; v += tv * ((float)ov->weights[b] / 255.0f); n += tn * ((float)ov->weights[b] / 255.0f); } } vertices[i] = v; if (supportVBO) vertices[header.nVertices + i] = n.normalize(); // shouldn't these be normal by default? else normals[i] = n; } if (supportVBO) glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); } for (size_t i=0; i<header.nLights; i++) {
if (lights[i].parent>=0) {
lights[i].tpos = bones[lights[i].parent].mat * lights[i].pos;
lights[i].tdir = bones[lights[i].parent].mrot * lights[i].dir;
}
}
for (size_t i=0; i<header.nParticleEmitters; i++) {
// random time distribution for teh win ..?
int pt = a.timeStart + (t + (int)(tmax*particleSystems[i].tofs)) % tmax;
particleSystems[i].setup(anim, pt);
}
for (size_t i=0; i<header.nRibbonEmitters; i++) {
ribbons[i].setup(anim, t);
}
if (animTextures) { for (size_t i=0; i<header.nTexAnims; i++) {
texanims[i].calc(anim, t);
}
}}bool ModelRenderPass::init(Model *m){ // blend mode switch (blendmode) { case BM_OPAQUE: // 0 glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); break; case BM_TRANSPARENT: // 1 glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST); break; case BM_ALPHA_BLEND: // 2 glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); //glEnable(GL_DEPTH_TEST); //? // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // default blend func break; case BM_ADDITIVE: // 3 glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_COLOR, GL_ONE); break; case BM_ADDITIVE_ALPHA: // 4 glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; default: // ??? glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); } if (nozwrite) { glDepthMask(GL_FALSE); //glDepthFunc(GL_GEQUAL); } if (cull) { glCullFace(GL_BACK); glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } GLuint bindtex = 0;
if (m->specialTextures[tex]==-1)
bindtex = m->textures[tex];
else
bindtex = m->replaceTextures[m->specialTextures[tex]];
glBindTexture(GL_TEXTURE_2D, bindtex);
if (swrap) {
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); } if (twrap) {
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); }
/*
if (usetex2) {
glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture2);
} */ if (unlit) { glDisable(GL_LIGHTING); // unfogged = unlit? //glDisable(GL_FOG); } if (useenvmap) { // env mapping glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
const GLint maptype = GL_SPHERE_MAP;
//const GLint maptype = GL_REFLECTION_MAP_ARB;
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, maptype);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, maptype);
}
if (texanim!=-1) {
glMatrixMode(GL_TEXTURE);
glPushMatrix();
m->texanims[texanim].setup();
}
Vec4D ocol(1,1,1,m->trans);
Vec4D ecol(0,0,0,0);
// emissive colors
if (color!=-1) {
Vec3D c = m->colors[color].color.getValue(m->anim,m->animtime);
float o = m->colors[color].opacity.getValue(m->anim,m->animtime);
ocol.w *= o;
if (unlit) {
ocol.x = c.x; ocol.y = c.y; ocol.z = c.z;
} else {
ocol.x = ocol.y = ocol.z = 0;
}
ecol = Vec4D(c, ocol.w);
}
glMaterialfv(GL_FRONT, GL_EMISSION, ecol);
// opacity
if (opacity!=-1) {
ocol.w *= m->transparency[opacity].trans.getValue(m->anim,m->animtime);
}
// color
glColor4fv(ocol);
if (blendmode<=1 && ocol.w!=1.0f) glEnable(GL_BLEND);
//return (ocol.w > 0) || (ecol.lengthSquared() > 0);
return m->showGeosets[geoset] && ( (ocol.w > 0) && (color==-1 || (ecol.w > 0)) );
}void ModelRenderPass::deinit(){ switch (blendmode) { case BM_OPAQUE: break; case BM_TRANSPARENT: break; case BM_ALPHA_BLEND: //glDepthMask(GL_TRUE); //glEnable(GL_DEPTH_TEST); //?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -