📄 modelcanvas.cpp
字号:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(vPos.x, vPos.y, -vPos.z);
glRotatef(vRot.x, 1.0f, 0.0f, 0.0f);
glRotatef(vRot.y, 0.0f, 1.0f, 0.0f);
glRotatef(vRot.z, 0.0f, 0.0f, 1.0f);
glTranslatef(baseTrans.x, baseTrans.y, baseTrans.z);
}
// render our main model
if (model || wmo) {
glDisable(GL_CULL_FACE);
root->draw(this);
// render our particles, we do this afterwards so that all the particles display "OK" without having things like shields "overwriting" the particles.
if (drawParticles && !drawMask && modelType!=MT_WMO) {
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
//glDisable(GL_CULL_FACE);
glDepthMask(GL_FALSE);
root->drawParticles(this);
glDepthMask(GL_TRUE);
}
}
// Draws our "lighting direction guide-line"
if (drawLightDir) {
glRotatef(vRot.y, 0.0f, -1.0f, 0.0f);
glBegin(GL_LINES);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(lPos.x, lPos.y, lPos.z);
glEnd();
}
//}
glFlush();
SwapBuffers();
}
void Attachment::draw(ModelCanvas *c)
{
if (!c)
return;
glPushMatrix();
if (model) {
model->reset();
setup();
// no need to scale if its already 100%
if (scale != 1.0f)
glScalef(scale, scale, scale);
if (c->drawModel) {
if(c->drawMask) {
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
} else {
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
//glDepthFunc(GL_LEQUAL);
}
model->draw();
// Disable lighting and textures if we haven't already
if(!c->drawMask) {
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
}
if (c->viewingModel) {
Model *m = static_cast<Model*>(model);
if (!m)
return;
if (!c->drawModel) {
m->trans = 0.0f;
m->draw();
m->trans = 1.0f;
}
if (c->drawBounds)
m->drawBoundingVolume();
if (c->drawBones)
m->drawBones();
}
}
}
// children:
for (size_t i=0; i<children.size(); i++) {
children[i]->draw(c);
}
glPopMatrix();
}
void Attachment::drawParticles(ModelCanvas *c)
{
if (!c)
return;
glPushMatrix();
if (model) {
Model *m = static_cast<Model*>(model);
if (!m)
return;
model->reset();
setup();
if (c->modelType!=MT_WMO && m->hasParticles)
m->drawParticles();
}
// children:
for (size_t i=0; i<children.size(); i++)
children[i]->drawParticles(c);
glPopMatrix();
}
void Attachment::tick(float dt)
{
if (model)
model->update(dt);
for (size_t i=0; i<children.size(); i++)
children[i]->tick(dt);
}
void ModelCanvas::OnTimer(wxTimerEvent& event)
{
if (bSaving == false) {
tick();
Refresh(false);
}
}
void ModelCanvas::OnIdle(wxIdleEvent& event)
{
if (bSaving == true) {
tick();
Refresh(false);
}
}
void ModelCanvas::tick()
{
static DWORD lastTime = timeGetTime();
int ddt = 0;
// Time stuff
//time = float();
ddt = (timeGetTime() - lastTime) * animSpeed;
lastTime = timeGetTime();
// --
AnimManager *animManager = NULL;
globalTime += (ddt);
if (model) {
if (model->animManager) {
animManager = model->animManager;
if (animManager->IsPaused())
ddt = 0;
else if (!animManager->IsParticlePaused())
ddt = animManager->GetTimeDiff();
}
//animManager->Tick(ddt);
root->tick(ddt);
//root->tick(ddt/1000.0f);
//} else if (wmo) {
// root->tick(ddt/1000.0f);
}
if (drawSky && skyModel && skyModel->animManager) {
animManager = skyModel->animManager;
//animManager->Tick(ddt);
sky->tick(ddt);
}
}
/*
void ModelCanvas::TogglePause()
{
if (!bPaused) {
// pause
bPaused = true;
pauseTime = timeGetTime();
} else {
// unpause
DWORD t = timeGetTime();
deltaTime += t - pauseTime;
if (time==0) deltaTime = t;
bPaused = false;
}
}
*/
void ModelCanvas::ResetView()
{
vRot = Vec3D(0,-90,0);
vPos = Vec3D(0, 0, 5);
bool isSkyBox = (model->name.substr(0,3)=="Env");
if (!isSkyBox) {
if (model->name.find("SkyBox")<model->name.length()) isSkyBox = true;
}
if (isSkyBox) {
// for skyboxes, don't zoom out ;)
vPos.y = vPos.z = 0.0f;
} else {
vPos.z = model->rad * 2.0f;
if (vPos.z < 3.0f) vPos.z = 3.0f;
if (vPos.z > 500.0f) vPos.z = 500.0f;
//ofsy = (model->anims[model->currentAnim].boxA.y + model->anims[model->currentAnim].boxB.y) * 0.5f;
vPos.y = -model->rad * 0.5f;
if (vPos.y > 50) vPos.y = 50;
if (vPos.y < -50) vPos.y = -50;
}
modelsize = model->rad * 2.0f;
if (model->name.substr(0,4)=="Item") vRot.y = 0; // items look better facing right by default
}
void ModelCanvas::ResetViewWMO(int id)
{
if (!wmo || id>=wmo->nGroups) return;
vRot = Vec3D(0.0f, -90.0f, 0.0f);
vPos = Vec3D(0.0f, 0.0f, 5.0f);
Vec3D mid;
if (id==-1) {
vPos.z = (wmo->v2-wmo->v1).length();
mid = (wmo->v1+wmo->v2)*0.5f;
} else {
// zoom/center on current WMO group
WMOGroup &g = wmo->groups[id];
vPos.z = (g.v2-g.v1).length();
mid = (g.v1+g.v2)*0.5f;
}
modelsize = vPos.z;
baseTrans = Vec3D(mid.x,mid.z,-mid.y) * -1.0f;
if (vPos.z < 3.0f) vPos.z = 3.0f;
if (vPos.z > 500.0f) vPos.z = 500.0f;
}
void ModelCanvas::loadBackground(wxString filename)
{
FILE *file = NULL;
BYTE *buffer = NULL;
//GLint format = GL_RGBA;
CxImage *image = NULL;
if (!wxFile::Exists(filename))
return;
file = fopen(filename.fn_str(), "rb");
if (!file) {
fclose(file);
return;
}
bgImagePath = filename;
// Setup the OpenGL Texture stuff
glGenTextures(1, &bgTexture);
glBindTexture(GL_TEXTURE_2D, bgTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
// Get the file extension and load the file
wxString tmp = filename.Mid(filename.Length() - 3, 3);
tmp.LowerCase();
if (tmp == "bmp")
image = new CxImage(file, CXIMAGE_FORMAT_BMP);
else if (tmp == "tga")
image = new CxImage(file, CXIMAGE_FORMAT_TGA);
else if (tmp == "jpg")
image = new CxImage(file, CXIMAGE_FORMAT_JPG);
else {
fclose(file);
return;
}
if (image == NULL) {
fclose(file);
return;
}
// TODO: Check the size of the images, resize as needed?
bool textureXSafe = false;
bool textureYSafe = false;
for (int i=2; i < 2100; i+=i) {
if (image->GetWidth() == i)
textureXSafe = true;
if (image->GetHeight() == i)
textureYSafe = true;
}
if (!textureXSafe || !textureYSafe) {
wxMessageBox(_T("The dimensions of that image are not to a power of 2. eg. 64x64, 128x128, 256x256, 512x512\nThis may result in unstable results, resizing to 256x256"), _T("Caution!"));
if (image->GetBpp() < 24)
image->IncreaseBpp(24);
image->Resample(256,256);
}
long size = image->GetWidth() * image->GetHeight() * 4;
image->Encode2RGBA(buffer, size);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image->GetWidth(), image->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
drawBackground = true;
fclose(file);
delete image;
delete buffer;
}
void ModelCanvas::Zoom(float f, bool rel)
{
if (rel) {
float cosx = cos(vRot.x * piover180);
vPos.x += cos(vRot.y * piover180) * cosx * f;
vPos.y += sin(vRot.x * piover180) * sin(vRot.y * piover180) * f;
vPos.z += sin(vRot.y * piover180) * cosx * f;
} else {
vPos.z -= f;
}
viewControl->Refresh();
}
// Check for keyboard input
void ModelCanvas::OnKey(wxKeyEvent &event)
{
// error checking
if(!model)
return;
// Make sure its the canvas that has focus before continuing
/*
wxWindow *win = wxWindow::FindFocus();
if(!win)
return;
wxGLCanvas *gl = wxDynamicCast(win, wxGLCanvas);
if(!gl)
return;
*/
// --
int keycode = event.GetKeyCode();
// animation speed toggles
if (keycode == '0') animControl->SetAnimSpeed(1.0f);
else if (keycode == '1') animControl->SetAnimSpeed(0.1f);
else if (keycode == '2') animControl->SetAnimSpeed(0.2f);
else if (keycode == '3') animControl->SetAnimSpeed(0.3f);
else if (keycode == '4') animControl->SetAnimSpeed(0.4f);
else if (keycode == '5') animControl->SetAnimSpeed(0.5f);
else if (keycode == '6') animControl->SetAnimSpeed(0.6f);
else if (keycode == '7') animControl->SetAnimSpeed(0.7f);
else if (keycode == '8') animControl->SetAnimSpeed(0.8f);
else if (keycode == '9') animControl->SetAnimSpeed(0.9f);
// --
// Turning
if (wxGetKeyState(WXK_LEFT)) {
vRot.y += (2.4f * animSpeed);
viewControl->Refresh();
if (vRot.y > 360) vRot.y -= 360;
if (vRot.y < 0) vRot.y += 360;
} else if (wxGetKeyState(WXK_RIGHT)) {
vRot.y -= (2.4f * animSpeed);
viewControl->Refresh();
if (vRot.y > 360) vRot.y -= 360;
if (vRot.y < 0) vRot.y += 360;
}
// --
// Moving forward/backward
float speed = 0.0f;
if ((modelType!=MT_WMO) && (model->animated==true))
speed = (model->anims[model->currentAnim].moveSpeed / 80.0f) * animSpeed;
else
speed = 2.0f * animSpeed;
if (wxGetKeyState(WXK_UP))
Zoom(speed, true);
else if (wxGetKeyState(WXK_DOWN))
Zoom(-speed, true);
// --
}
/*
void ModelCanvas::SetFrame(int frame)
{
//
}
*/
void Attachment::setup()
{
if (parent==0)
return;
if (parent->model)
parent->model->setupAtt(id);
}
Attachment* Attachment::addChild(const char *modelfn, int id, int slot, float scale)
{
if (!modelfn || !strlen(modelfn) || id<0) return 0;
Model *m = new Model(modelfn, true);
if (m && m->ok) {
return addChild(m, id, slot, scale);
} else {
delete m;
return 0;
}
}
Attachment* Attachment::addChild(Displayable *disp, int id, int slot, float scale)
{
Attachment *att = new Attachment(this, disp, id, slot, scale);
children.push_back(att);
return att;
}
void Attachment::delChildren()
{
for (size_t i=0; i<children.size(); i++) delete children[i];
children.clear();
}
void Attachment::delSlot(int slot)
{
for (size_t i=0; i<children.size(); ) {
if (children[i]->slot == slot) {
delete children[i];
children.erase(children.begin() + i);
} else i++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -