// --[ Method ]--------------------------------------------------------------- // // - Class : CVector3 // - Prototype : bool operator != (const CVector3& vector) const // // - Purpose : Comparison operator // // --------------------------------------------------------------------------- bool CVector3::operator != (const CVector3& vector) const { if(!ARE_EQUAL(vector.X(), m_fX)) return true; if(!ARE_EQUAL(vector.Y(), m_fY)) return true; if(!ARE_EQUAL(vector.Z(), m_fZ)) return true; return false; }
void tCreateImage() { fsm->generate(5, 3, 2); string path = DATA_PATH; path += "tmp/"; auto filename = fsm->writeDOTfile(path); ARE_EQUAL(true, !filename.empty(), "This %s cannot be saved into path '%s' in DOT format.", machineTypeNames[fsm->getType()], path.c_str()); ARE_EQUAL(true, FSMmodel::createGIF(filename, true), "GIF was not created/shown for %s", filename.c_str()); ARE_EQUAL(true, FSMmodel::createJPG(filename, true), "JPG was not created/shown for %s", filename.c_str()); ARE_EQUAL(true, FSMmodel::createPNG(filename, true), "PNG was not created/shown for %s", filename.c_str()); }
/// includes tests for getNumberOfStates/Inputs/Outputs() /// and confirms generate(), removeTransition(), removeState() void tGenerateSaveLoad() { DEBUG_MSG("Generate: %s", machineTypeNames[fsm->getType()]); fsm->generate(0, 0, 0);// = create(1,1,1) is minimum /// ERR: <type>::generate - the number of states needs to be greater than 0 (set to 1) /// ERR: <type>::generate - the number of inputs needs to be greater than 0 (set to 1) /// ERR: <type>::generate - the number of outputs needs to be greater than 0 (set to 1) ARE_EQUAL(fsm->getNumberOfStates(), state_t(1), "The number of states is not correct."); ARE_EQUAL(fsm->getNumberOfInputs(), input_t(1), "The number of inputs is not correct."); ARE_EQUAL(fsm->getNumberOfOutputs(), output_t(1), "The number of outputs is not correct."); tSaveLoad(); fsm->generate(5, 3, 2); ARE_EQUAL(fsm->getNumberOfStates(), state_t(5), "The number of states is not correct."); ARE_EQUAL(fsm->getNumberOfInputs(), input_t(3), "The number of inputs is not correct."); ARE_EQUAL(fsm->getNumberOfOutputs(), output_t(2), "The number of outputs is not correct."); tSaveLoad(); fsm->removeTransition(0, 0); fsm->removeTransition(1, 1); fsm->removeTransition(2, 2); /// 3 transitions * 2 machines = 6 ERRs if fsm->isOutputTransition() /// <type>::getOutput - there is no such transition fsm->removeState(3); /// if fsm->isOutputTransition() && there was a transition to state 3, then 2 ERRs: /// <type>::getOutput - there is no such transition tSaveLoad(); }
/// includes tests for getNumberOfStates/Inputs/Outputs() /// and confirms create(), removeTransition() void tCreateSaveLoad() { DEBUG_MSG("Create: %s", machineTypeNames[fsm->getType()]); fsm->create(0, 0, 0);// = create(1,0,0) is minimum /// ERR: <type>::create - the number of states needs to be greater than 0 (set to 1) ARE_EQUAL(fsm->getNumberOfStates(), state_t(1), "The number of states is not correct."); ARE_EQUAL(fsm->getNumberOfInputs(), input_t(0), "The number of inputs is not correct."); ARE_EQUAL(fsm->getNumberOfOutputs(), output_t(0), "The number of outputs is not correct."); tSaveLoad(); fsm->create(5, 3, 2); ARE_EQUAL(fsm->getNumberOfStates(), state_t(5), "The number of states is not correct."); ARE_EQUAL(fsm->getNumberOfInputs(), input_t(3), "The number of inputs is not correct."); ARE_EQUAL(fsm->getNumberOfOutputs(), output_t(2), "The number of outputs is not correct."); /// 5 states * 3 inputs * 2 machines = 30 ERRs if fsm->isOutputTransition() /// <type>::getOutput - there is no such transition tSaveLoad(); fsm->setTransition(0, 0, 0); fsm->setTransition(0, 1, 1); fsm->setTransition(0, 2, 2); fsm->setTransition(1, 0, 3); fsm->setTransition(2, 1, 4); fsm->setTransition(3, 2, 0); fsm->setTransition(4, 0, 2); /// (5 states * 3 inputs - 7 transitions) * 2 machines = 16 ERRs if fsm->isOutputTransition() /// <type>::getOutput - there is no such transition tSaveLoad(); }
bool CFXBillboardScene::DoFrame(CDemo* pDemo, float fEffectTime, float fDemoTime) { assert(pDemo); // Scene if(!m_pResScene) { FXRuntimeError("Scene resource not available"); return false; } CSceneView* pSceneView = const_cast<CSceneView*>(((CResourceScene*)m_pResScene)->GetSceneView()); if(!pSceneView) { FXRuntimeError("NULL pSceneView"); return false; } // Texture if(!m_pResTexture) { FXRuntimeError("Texture resource not found"); return false; } UtilGL::Texturing::CTexture2D* pTexture = const_cast<UtilGL::Texturing::CTexture2D*>(((CResourceTexture2D*)m_pResTexture)->GetTexture2D()); if(!pTexture) { FXRuntimeError("WARNING: Texture not available, effect will draw flat quad"); } // Vars CVarFloat::CValueFloat valueStartTime; CVarSpeed::CValueSpeed valueSpeed; CVarCombo::CValueCombo valueRenderMode; CVarString::CValueString valueCamera; CVarFloat::CValueFloat valueLoopLength; CVarFloat::CValueFloat valueLoopStart; CVarColor::CValueColor valueColor; CVarFloat::CValueFloat valueSize; CVarFloat::CValueFloat valueAlpha; CVarFloat::CValueFloat valueAngle; CVarCombo::CValueCombo valueBlendMode; CVarCombo::CValueCombo valueFiltering; EvaluateVar("Start Time", fEffectTime, &valueStartTime); EvaluateVar("Speed", fEffectTime, &valueSpeed); EvaluateVar("Render Mode", fEffectTime, &valueRenderMode); EvaluateVar("Camera", fEffectTime, &valueCamera); EvaluateVar("Loop Length", fEffectTime, &valueLoopLength); EvaluateVar("Loop Start", fEffectTime, &valueLoopStart); EvaluateVar("Color", fEffectTime, &valueColor); EvaluateVar("Size", fEffectTime, &valueSize); EvaluateVar("Alpha", fEffectTime, &valueAlpha); EvaluateVar("Angle", fEffectTime, &valueAngle); EvaluateVar("Blend Mode", fEffectTime, &valueBlendMode); EvaluateVar("Filtering", fEffectTime, &valueFiltering); float fAlpha = valueAlpha.GetValue(); CVector4 v4Color = valueColor.GetValue(); v4Color.SetW(fAlpha); if(valueCamera.GetString() != m_strCamera) { // Camera string changed at runtime m_strCamera = valueCamera.GetString(); } float fTime = valueStartTime.GetValue() + valueSpeed.Integrate(0.0f, fEffectTime); if(IS_ZERO(valueLoopLength.GetValue())) { ComputeLoop(valueLoopStart.GetValue(), m_fAnimEnd, &fTime); } else if(valueLoopLength.GetValue() > 0.0f) { ComputeLoop(valueLoopStart.GetValue(), valueLoopLength.GetValue(), &fTime); } pSceneView->SetActiveCamera(m_strCamera); CRenderVisitor::EMode eRenderMode = CRenderVisitor::MODE_FULLDETAIL; if(valueRenderMode.GetValue() == "Full") eRenderMode = CRenderVisitor::MODE_FULLDETAIL; else if(valueRenderMode.GetValue() == "Solid") eRenderMode = CRenderVisitor::MODE_SOLID; else if(valueRenderMode.GetValue() == "Wire") eRenderMode = CRenderVisitor::MODE_WIREFRAME; CMatrix mtxAddLocal, mtxAddWorld; CVector3 v3AddCamPos, v3AddCamAngles; EvaluateAddTransformVars(this, fEffectTime, &mtxAddLocal, &mtxAddWorld, &v3AddCamPos, &v3AddCamAngles); pSceneView->Transform(pDemo, fTime, mtxAddLocal, mtxAddWorld, v3AddCamPos, v3AddCamAngles); // States UtilGL::States::SetColor(v4Color); // Change filter mode bool bTextureAlpha = false; GLint minFilter, magFilter; if(pTexture) { pTexture->SetActive(); if(pTexture->HasAlpha()) { bTextureAlpha = true; } glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &minFilter); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &magFilter); if(valueFiltering.GetValue() == "Yes") { // If it's point filtering, change it to linear, otherwise leave it as it is if(minFilter == GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if(magFilter == GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } } // Blending int nSrcBlend = UtilGL::States::BLEND_SRCALPHA; int nDstBlend = UtilGL::States::BLEND_INVSRCALPHA; if(valueBlendMode.GetValue() == "Add") nDstBlend = UtilGL::States::BLEND_ONE; else if(valueBlendMode.GetValue() == "Mult") nDstBlend = UtilGL::States::BLEND_INVSRCALPHA; if(ARE_EQUAL(fAlpha, 1.0f) && valueBlendMode.GetValue() == "Mult" && !bTextureAlpha) { nSrcBlend = UtilGL::States::BLEND_ONE; nDstBlend = UtilGL::States::BLEND_ZERO; } if(!((nSrcBlend == UtilGL::States::BLEND_ONE && nDstBlend == UtilGL::States::BLEND_ZERO) || (nSrcBlend == UtilGL::States::BLEND_ZERO && nDstBlend == UtilGL::States::BLEND_ONE))) { UtilGL::States::Set(UtilGL::States::BLENDING, UtilGL::States::ENABLED); UtilGL::States::Set(UtilGL::States::SRCBLEND, nSrcBlend); UtilGL::States::Set(UtilGL::States::DSTBLEND, nDstBlend); } else { UtilGL::States::Set(UtilGL::States::BLENDING, UtilGL::States::DISABLED); } UtilGL::States::Set(UtilGL::States::LIGHTING, UtilGL::States::DISABLED); UtilGL::States::Set(UtilGL::States::ZBUFFERWRITE, UtilGL::States::DISABLED); UtilGL::States::Set(UtilGL::States::ALPHATEST, UtilGL::States::ENABLED); glAlphaFunc(GL_GREATER, 0.0f); CEnumVisitor enumVisitor(CNodeVisitor::TRAVERSAL_DOWNWARDS); enumVisitor.Reset(); if(pSceneView->GetRootNode()) { CNode* pRootNode = (CNode*)pSceneView->GetRootNode(); pRootNode->AcceptVisitor(&enumVisitor); } if(valueRenderMode.GetValue() == "Solid") { pTexture = NULL; } else if(valueRenderMode.GetValue() == "Wire") { pTexture = NULL; UtilGL::States::Set(UtilGL::States::POLYGONMODE, UtilGL::States::POLYGONMODE_LINE); } for(int i = 0; i < enumVisitor.GetNumObjects(); i++) { CObject* pObject = enumVisitor.GetObject(i); UtilGL::Transforming::SetMatrix(UtilGL::Transforming::MATRIX_WORLD, pObject->GetAbsoluteTM()); UtilGL::Rendering::DrawBillboards( pObject->GetNumVertices(), pTexture, pObject->GetVertices(), NULL, valueSize.GetValue(), valueAngle.GetValue()); } if(pTexture) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); } UtilGL::States::Set(UtilGL::States::BLENDING, UtilGL::States::DISABLED); UtilGL::States::Set(UtilGL::States::ALPHATEST, UtilGL::States::DISABLED); UtilGL::States::Set(UtilGL::States::POLYGONMODE, UtilGL::States::POLYGONMODE_FILL); UtilGL::States::Set(UtilGL::States::ZBUFFERWRITE, UtilGL::States::ENABLED); return true; }
/// includes tests for getNumberOfStates/Inputs/Outputs(), getType(), /// isReduced(), isOutputState/Transition(), getStates(), addState(), removeState() /// save(), load() /// confirms getOutput(), getNextState() void tSaveLoad() { string path = DATA_PATH; path += "tmp/"; string filename = fsm->save(path); ARE_EQUAL(!filename.empty(), true, "This %s cannot be saved into path '%s'.", machineTypeNames[fsm->getType()], path.c_str()); ARE_EQUAL(fsm2->load(filename), true, "File '%s' cannot be loaded.", filename.c_str()); DEBUG_MSG(filename.c_str()); ARE_EQUAL(fsm->getType(), fsm2->getType(), "Types of machines are not equal."); ARE_EQUAL(fsm->getNumberOfStates(), fsm2->getNumberOfStates(), "The numbers of states are not equal."); ARE_EQUAL(fsm->getNumberOfInputs(), fsm2->getNumberOfInputs(), "The numbers of inputs are not equal."); ARE_EQUAL(fsm->getNumberOfOutputs(), fsm2->getNumberOfOutputs(), "The numbers of outputs are not equal."); ARE_EQUAL(fsm->isReduced(), fsm2->isReduced(), "The indicators of minimal form are not equal."); ARE_EQUAL(fsm->isOutputState(), fsm2->isOutputState(), "The indicators of state outputs are not equal."); ARE_EQUAL(fsm->isOutputTransition(), fsm2->isOutputTransition(), "The indicators of transition outputs are not equal."); auto states = fsm->getStates(); ARE_EQUAL(fsm->getNumberOfStates(), state_t(states.size()), "The numbers of states are not equal."); auto states2 = fsm2->getStates(); ARE_EQUAL(states == states2, true, "The sets of states are not equal."); ARE_EQUAL((find(states.begin(), states.end(), 0) != states.end()), true, "The initial state is missing."); for (state_t& state : states) { if (fsm->isOutputState()) { ARE_EQUAL(fsm->getOutput(state, STOUT_INPUT), fsm2->getOutput(state, STOUT_INPUT), "The outputs of state %d are different.", state); } for (input_t i = 0; i < fsm->getNumberOfInputs(); i++) { state_t nextState = fsm->getNextState(state, i); //DEBUG_MSG("%d", nextState); if (fsm->isOutputTransition()) { output_t output = fsm->getOutput(state, i); ARE_EQUAL(output, fsm2->getOutput(state, i), "The outputs on input %d from state %d are different.", i, state); if (nextState == NULL_STATE) { ARE_EQUAL(WRONG_OUTPUT, output, "There is no transition on input %d from state %d but output %d is set.", i, state, output); } } ARE_EQUAL(nextState, fsm2->getNextState(state, i), "The next states on input %d from state %d are different.", i, state); ARE_EQUAL(nextState != WRONG_STATE, true, "The next state on input %d from state %d is wrong.", i, state); if (nextState != NULL_STATE) { ARE_EQUAL((find(states.begin(), states.end(), nextState) != states.end()), true, "The next state is wrong."); } } } auto newState = fsm->addState(); //DEBUG_MSG("%d", newState); ARE_EQUAL(fsm->getNumberOfStates(), fsm2->getNumberOfStates() + 1, "The numbers of states are to be different by one."); ARE_EQUAL(newState, fsm2->addState(), "IDs of new states are not equal."); ARE_EQUAL(fsm->getNumberOfStates(), fsm2->getNumberOfStates(), "The numbers of states are not equal."); fsm->removeState(newState); ARE_EQUAL(fsm->getNumberOfStates(), fsm2->getNumberOfStates() - 1, "The numbers of states are to be different by one."); }
bool CFXMosaic::DoFrame(CDemo* pDemo, float fEffectTime, float fDemoTime) { assert(pDemo); if(!m_pResTexture) { FXRuntimeError("Texture resource not found"); return false; } UtilGL::Texturing::CTexture2D* pTexture = const_cast<UtilGL::Texturing::CTexture2D*>(((CResourceTexture2D*)m_pResTexture)->GetTexture2D()); if(!pTexture) { FXRuntimeError("WARNING: Texture not available"); return false; } if(m_vecTiles.size() < 1) { FXRuntimeError("WARNING: No tiles available"); return false; } CVarFloat::CValueFloat valuePosX; CVarFloat::CValueFloat valuePosY; CVarFloat::CValueFloat valueWidth; CVarFloat::CValueFloat valueHeight; CVarFloat::CValueFloat valueScale; CVarFloat::CValueFloat valueAlpha; CVarFloat::CValueFloat valueAngle; CVarCombo::CValueCombo valueBlendMode; CVarCombo::CValueCombo valueFiltering; CVarInt::CValueInt valueTilesX; CVarInt::CValueInt valueTilesY; CVarInt::CValueInt valueTileSourceWidth; CVarInt::CValueInt valueTileSourceHeight; CVarFloat::CValueFloat valueChangeFrequency; CVarFloat::CValueFloat valueChangeFreqVariation; EvaluateVar("X Position", fEffectTime, &valuePosX); EvaluateVar("Y Position", fEffectTime, &valuePosY); EvaluateVar("Width", fEffectTime, &valueWidth); EvaluateVar("Height", fEffectTime, &valueHeight); EvaluateVar("Scale", fEffectTime, &valueScale); EvaluateVar("Alpha", fEffectTime, &valueAlpha); EvaluateVar("Angle", fEffectTime, &valueAngle); EvaluateVar("Blend Mode", fEffectTime, &valueBlendMode); EvaluateVar("Filtering", fEffectTime, &valueFiltering); EvaluateVar("Tiles X", fEffectTime, &valueTilesX); EvaluateVar("Tiles Y", fEffectTime, &valueTilesY); EvaluateVar("Tile Source Width", fEffectTime, &valueTileSourceWidth); EvaluateVar("Tile Source Height", fEffectTime, &valueTileSourceHeight); EvaluateVar("Change Frequency", fEffectTime, &valueChangeFrequency); EvaluateVar("Change Freq Variation", fEffectTime, &valueChangeFreqVariation); // Change filter mode GLint minFilter, magFilter; GLfloat fMaxAnisotropy; UtilGL::States::Set(UtilGL::States::TEXTURE2D, UtilGL::States::ENABLED); pTexture->SetActive(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &minFilter); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &magFilter); if(UtilGL::Extensions::GetAvailableExtensions()->EXT_texture_filter_anisotropic) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fMaxAnisotropy); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f); } if(valueFiltering.GetValue() == "Yes") { // If it's point filtering, change it to linear, otherwise leave it as it is if(minFilter == GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if(magFilter == GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } CVarFloat* pVarAngle = reinterpret_cast<CVarFloat*>(GetVar("Angle")); assert(pVarAngle); float fAlpha = valueAlpha.GetValue() > 1.0f ? 1.0f : valueAlpha.GetValue(); if(fAlpha < ALMOST_ZERO) { return true; } CVector4 v4Color(1.0f, 1.0f, 1.0f, fAlpha); UtilGL::States::SetColor(v4Color); float fAngle = valueAngle.GetValue(); if(IS_ZERO(fAngle) && !pVarAngle->IsConstant()) { // Avoid aspect ratio problem (see UtilGL::Rendering::DrawRect()) fAngle = fAngle < 0.0f ? fAngle - (ALMOST_ZERO * 2.0f) : fAngle + (ALMOST_ZERO * 2.0f); } int nSrcBlend = UtilGL::States::BLEND_SRCALPHA; int nDstBlend = UtilGL::States::BLEND_INVSRCALPHA; if(valueBlendMode.GetValue() == "Add") nDstBlend = UtilGL::States::BLEND_ONE; else if(valueBlendMode.GetValue() == "Mult") nDstBlend = UtilGL::States::BLEND_INVSRCALPHA; else if(valueBlendMode.GetValue() == "Color Mult") { nSrcBlend = UtilGL::States::BLEND_DSTCOLOR; nDstBlend = UtilGL::States::BLEND_ZERO; } if(ARE_EQUAL(fAlpha, 1.0f) && valueBlendMode.GetValue() == "Mult" && !pTexture->HasAlpha()) { nSrcBlend = UtilGL::States::BLEND_ONE; nDstBlend = UtilGL::States::BLEND_ZERO; } if(!((nSrcBlend == UtilGL::States::BLEND_ONE && nDstBlend == UtilGL::States::BLEND_ZERO) || (nSrcBlend == UtilGL::States::BLEND_ZERO && nDstBlend == UtilGL::States::BLEND_ONE))) { UtilGL::States::Set(UtilGL::States::BLENDING, UtilGL::States::ENABLED); UtilGL::States::Set(UtilGL::States::SRCBLEND, nSrcBlend); UtilGL::States::Set(UtilGL::States::DSTBLEND, nDstBlend); } else { UtilGL::States::Set(UtilGL::States::BLENDING, UtilGL::States::DISABLED); } UtilGL::States::Set(UtilGL::States::LIGHTING, UtilGL::States::DISABLED); UtilGL::States::Set(UtilGL::States::ZBUFFER, UtilGL::States::DISABLED); UtilGL::Transforming::ClearMatrix(UtilGL::Transforming::MATRIX_WORLD); UtilGL::Transforming::ClearMatrix(UtilGL::Transforming::MATRIX_VIEW); UtilGL::Transforming::ClearMatrix(UtilGL::Transforming::MATRIX_PROJECTION); glMatrixMode(GL_PROJECTION); glOrtho(0, pTexture->GetWidth(), pTexture->GetHeight(), 0, 0.0f, 10.0f); // Update *********** int nImgTilesX = pTexture && valueTileSourceWidth.GetValue() > 0 ? pTexture->GetWidth() / valueTileSourceWidth.GetValue() : 1; int nImgTilesY = pTexture && valueTileSourceHeight.GetValue() > 0 ? pTexture->GetHeight() / valueTileSourceHeight.GetValue() : 1; float fChangePeriod = IS_ZERO(valueChangeFrequency.GetValue()) ? FLOAT_MAX : 1.0f / valueChangeFrequency.GetValue(); if(fChangePeriod < 0.0001f) fChangePeriod = 0.0001f; while(MYFABSF(m_fLastUpdate - fEffectTime) > fChangePeriod) { int nRandTile = rand() % m_vecTiles.size(); m_vecTiles[nRandTile].nImgTileX = rand() % nImgTilesX; m_vecTiles[nRandTile].nImgTileY = rand() % nImgTilesY; if(fEffectTime < m_fLastUpdate) { m_fLastUpdate -= fChangePeriod; } else { m_fLastUpdate += fChangePeriod; } } // Render *********** VECTILES::iterator it; float fUTileWidth = (float)valueTileSourceWidth.GetValue() / (float)pTexture->GetWidth(); float fVTileHeight = (float)valueTileSourceHeight.GetValue() / (float)pTexture->GetHeight(); int nTilesX = valueTilesX.GetValue() < 1 ? 1 : valueTilesX.GetValue(); int nTilesY = valueTilesY.GetValue() < 1 ? 1 : valueTilesY.GetValue(); for(it = m_vecTiles.begin(); it < m_vecTiles.end(); ++it) { STile tile = *it; float fTileWidth = pTexture->GetWidth() / (float)nTilesX; float fTileHeight = pTexture->GetHeight() / (float)nTilesY; float fPosX = ((valuePosX.GetValue() - 0.5f) * pTexture->GetWidth()) + (fTileWidth * tile.nX); float fPosY = ((valuePosY.GetValue() - 0.5f) * pTexture->GetHeight()) + (fTileHeight * tile.nY); float fScaleX = valueWidth.GetValue() * valueScale.GetValue(); float fScaleY = valueHeight.GetValue() * valueScale.GetValue(); float fU = tile.nImgTileX * fUTileWidth; float fV = 1.0f - (tile.nImgTileY * fVTileHeight); float fU2 = fU + fUTileWidth; float fV2 = fV - fVTileHeight; CVector3 v3Center(pTexture->GetWidth() * 0.5f, pTexture->GetHeight() * 0.5f, -5.0f); CMatrix worldMtx; worldMtx.SetIdentity(); worldMtx.Translate(fPosX, fPosY, 0.0f); worldMtx.Translate(-v3Center.X(), -v3Center.Y(), 0.0f); worldMtx.Scale (fScaleX, fScaleY, 1.0f); worldMtx.RotateZ (fAngle); worldMtx.Translate(+v3Center.X(), +v3Center.Y(), 0.0f); UtilGL::Transforming::SetMatrix(UtilGL::Transforming::MATRIX_WORLD, worldMtx); glBegin(GL_QUADS); glTexCoord2f(fU, fV); glVertex3f(0.0f, 0.0f, -5.0f); glTexCoord2f(fU, fV2); glVertex3f(0.0f, fTileHeight, -5.0f); glTexCoord2f(fU2, fV2); glVertex3f(fTileWidth, fTileHeight, -5.0f); glTexCoord2f(fU2, fV); glVertex3f(fTileWidth, 0.0f, -5.0f); glEnd(); } glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0f, pDemo->GetAspect(), 1.0f, 1000.0f); // Restore filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); UtilGL::States::Set(UtilGL::States::TEXTURE2D, UtilGL::States::DISABLED); if(UtilGL::Extensions::GetAvailableExtensions()->EXT_texture_filter_anisotropic) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fMaxAnisotropy); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fMaxAnisotropy); } UtilGL::States::Set(UtilGL::States::TEXTURE2D, UtilGL::States::DISABLED); UtilGL::States::Set(UtilGL::States::BLENDING, UtilGL::States::DISABLED); UtilGL::States::Set(UtilGL::States::ZBUFFER, UtilGL::States::ENABLED); return true; }
// --[ Method ]--------------------------------------------------------------- // // - Class : CStravaganzaMaxTools // // - prototype : bool BuildShaders() // // - Purpose : Builds the shader list from MAX's materials. // Preview mode requires texture files to be stored with full // path in order to load them. When we export, we only store the // filename. Another thing is that in the export mode, we copy // all textures into the path specified by the user if that // option is checked. // // ----------------------------------------------------------------------------- bool CStravaganzaMaxTools::BuildShaders() { std::vector<Mtl*>::iterator it; assert(m_vecShaders.empty()); if(!m_bPreview && m_bCopyTextures && m_strTexturePath == "") { CLogger::NotifyWindow("Textures won't be copied\nSpecify a valid output texture path first"); } LOG.Write("\n\n-Building shaders: "); for(it = m_vecMaterials.begin(); it != m_vecMaterials.end(); ++it) { Mtl* pMaxMaterial = *it; assert(pMaxMaterial); LOG.Write("\n %s", pMaxMaterial->GetName().data()); CShaderStandard* pShaderStd = new CShaderStandard; pShaderStd->SetName(pMaxMaterial->GetName().data()); // Properties StdMat2 *pMaxStandardMtl = NULL; StdMat2 *pMaxBakedMtl = NULL; float fAlpha; if(pMaxMaterial->ClassID() == Class_ID(DMTL_CLASS_ID, 0)) { pMaxStandardMtl = (StdMat2 *)pMaxMaterial; } else if(pMaxMaterial->ClassID() == Class_ID(BAKE_SHELL_CLASS_ID, 0)) { pMaxStandardMtl = (StdMat2 *)pMaxMaterial->GetSubMtl(0); pMaxBakedMtl = (StdMat2 *)pMaxMaterial->GetSubMtl(1); } if(pMaxStandardMtl) { // Standard material fAlpha = pMaxStandardMtl->GetOpacity(0); Shader* pMaxShader = pMaxStandardMtl->GetShader(); CVector4 v4Specular = ColorToVector4(pMaxStandardMtl->GetSpecular(0), 0.0f) * pMaxShader->GetSpecularLevel(0, 0); pShaderStd->SetAmbient (ColorToVector4(pMaxStandardMtl->GetAmbient(0), 0.0f)); pShaderStd->SetDiffuse (ColorToVector4(pMaxStandardMtl->GetDiffuse(0), fAlpha)); pShaderStd->SetSpecular (v4Specular); pShaderStd->SetShininess(pMaxShader->GetGlossiness(0, 0) * 128.0f); if(pMaxStandardMtl->GetTwoSided() == TRUE) { pShaderStd->SetTwoSided(true); } // Need to cast to StdMat2 in order to get access to IsFaceted(). // ¿Is StdMat2 always the interface for standard materials? if(((StdMat2*)pMaxStandardMtl)->IsFaceted()) { pShaderStd->SetFaceted(true); } if(pMaxStandardMtl->GetWire() == TRUE) { pShaderStd->SetPostWire(true); pShaderStd->SetWireLineThickness(pMaxStandardMtl->GetWireSize(0)); } } else { // Material != Standard fAlpha = 1.0f; // pMaxMaterial->GetXParency(); pShaderStd->SetAmbient (ColorToVector4(pMaxMaterial->GetAmbient(), 0.0f)); pShaderStd->SetDiffuse (ColorToVector4(pMaxMaterial->GetDiffuse(), fAlpha)); pShaderStd->SetSpecular (CVector4(0.0f, 0.0f, 0.0f, 0.0f)); pShaderStd->SetShininess(0.0f); } // Layers if(!pMaxStandardMtl) { m_vecShaders.push_back(pShaderStd); continue; } bool bDiffuseMap32Bits = false; StdMat2 *pStandardMtl; for(int i = 0; i < 3; i++) { int nMap; pStandardMtl = pMaxStandardMtl; // 0 = diffuse, 1 == bump, 2 = lightmap (self illumination slot) or envmap (reflection slot) if(i == 0) { nMap = ID_DI; } else if(i == 1) { nMap = ID_BU; // If its a baked material, get the bump map from there if(pMaxBakedMtl) { pStandardMtl = pMaxBakedMtl; } } else if(i == 2) { bool bBaked = false; // If its a baked material, get the map2 (lightmap) from there if(pMaxBakedMtl) { if(pMaxBakedMtl->GetMapState(ID_SI) == MAXMAPSTATE_ENABLED) { bBaked = true; nMap = ID_SI; pStandardMtl = pMaxBakedMtl; } } if(!bBaked) { if(pStandardMtl->GetMapState(ID_SI) == MAXMAPSTATE_ENABLED) { nMap = ID_SI; } else { nMap = ID_RL; } } } // Check validity if(pStandardMtl->GetMapState(nMap) != MAXMAPSTATE_ENABLED) { if(i == 0) { LOG.Write("\n No diffuse. Skipping."); break; } continue; } Texmap* pMaxTexmap = pStandardMtl->GetSubTexmap(nMap); if(!pMaxTexmap) { if(i == 0) { LOG.Write("\n No diffuse. Skipping."); break; } continue; } // Get texmaps std::vector<std::string> vecTextures, vecPaths; CShaderStandard::SLayerInfo layerInfo; CShaderStandard::SBitmapInfo bitmapInfo; if(pMaxTexmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) { BitmapTex* pMaxBitmapTex = (BitmapTex*)pMaxTexmap; Bitmap* pMaxBitmap = pMaxBitmapTex->GetBitmap(SECONDS_TO_TICKS(m_fStartTime)); StdUVGen* pMaxUVGen = pMaxBitmapTex->GetUVGen(); if(!pMaxBitmap) { if(i == 0) { LOG.Write("\n Invalid diffuse. Skipping."); break; } continue; } assert(pMaxUVGen); BitmapInfo bi = pMaxBitmap->Storage()->bi; // bi.Name() returns the full path // bi.Filename() returns just the filename vecTextures.push_back(bi.Filename()); vecPaths. push_back(bi.Name()); LOG.Write("\n Bitmap %s", vecTextures[0].data()); // Check if diffuse texture has alpha channel if(i == 0) { CBitmap bitmap; CInputFile bitmapFile; if(!bitmapFile.Open(bi.Name(), false)) { CLogger::NotifyWindow("WARNING - CStravaganzaMaxTools::BuildShaders():\nUnable to load file %s", bi.Name()); } else { if(!bitmap.Load(&bitmapFile, GetFileExt(bi.Name()))) { CLogger::NotifyWindow("WARNING - CStravaganzaMaxTools::BuildShaders():\nUnable to load bitmap %s", bi.Name()); } else { if(bitmap.GetBpp() == 32) { bDiffuseMap32Bits = true; LOG.Write(" (with alpha channel)"); } bitmap.Free(); } bitmapFile.Close(); } } // Ok, copy properties layerInfo.texInfo.bLoop = false; layerInfo.texInfo.eTextureType = UtilGL::Texturing::CTexture::TEXTURE2D; bitmapInfo.strFile = m_bPreview ? bi.Name() : bi.Filename(); bitmapInfo.bTile = ((pMaxUVGen->GetTextureTiling() & (U_WRAP | V_WRAP)) == (U_WRAP | V_WRAP)) ? true : false; bitmapInfo.fSeconds = 0.0f; bitmapInfo.bForceFiltering = false; bitmapInfo.eFilter = UtilGL::Texturing::FILTER_TRILINEAR; // won't be used (forcefiltering = false) layerInfo.texInfo.m_vecBitmaps.push_back(bitmapInfo); layerInfo.eTexEnv = nMap == ID_RL ? CShaderStandard::TEXENV_ADD : CShaderStandard::TEXENV_MODULATE; layerInfo.eUVGen = pMaxUVGen->GetCoordMapping(0) == UVMAP_SPHERE_ENV ? CShaderStandard::UVGEN_ENVMAPPING : CShaderStandard::UVGEN_EXPLICITMAPPING; layerInfo.uMapChannel = pMaxUVGen->GetMapChannel(); layerInfo.v3ScrollSpeed = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3RotationSpeed = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3ScrollOffset = CVector3(pMaxUVGen->GetUOffs(0), pMaxUVGen->GetVOffs(0), 0.0f); layerInfo.v3RotationOffset = CVector3(pMaxUVGen->GetUAng(0), pMaxUVGen->GetVAng(0), pMaxUVGen->GetWAng(0)); } else if(pMaxTexmap->ClassID() == Class_ID(ACUBIC_CLASS_ID, 0)) { ACubic* pMaxCubic = (ACubic*)pMaxTexmap; IParamBlock2* pBlock = pMaxCubic->pblock; Interval validRange = m_pMaxInterface->GetAnimRange(); for(int nFace = 0; nFace < 6; nFace++) { int nMaxFace; switch(nFace) { case 0: nMaxFace = 3; break; case 1: nMaxFace = 2; break; case 2: nMaxFace = 1; break; case 3: nMaxFace = 0; break; case 4: nMaxFace = 5; break; case 5: nMaxFace = 4; break; } TCHAR *name; pBlock->GetValue(acubic_bitmap_names, TICKS_TO_SECONDS(m_fStartTime), name, validRange, nMaxFace); vecPaths.push_back(name); CStr path, file, ext; SplitFilename(CStr(name), &path, &file, &ext); std::string strFile = std::string(file.data()) + ext.data(); vecTextures.push_back(strFile); bitmapInfo.strFile = m_bPreview ? name : strFile; bitmapInfo.bTile = false; bitmapInfo.fSeconds = 0.0f; bitmapInfo.bForceFiltering = false; bitmapInfo.eFilter = UtilGL::Texturing::FILTER_TRILINEAR; layerInfo.texInfo.m_vecBitmaps.push_back(bitmapInfo); } layerInfo.texInfo.bLoop = false; layerInfo.texInfo.eTextureType = UtilGL::Texturing::CTexture::TEXTURECUBEMAP; layerInfo.eTexEnv = nMap == ID_RL ? CShaderStandard::TEXENV_ADD : CShaderStandard::TEXENV_MODULATE; layerInfo.eUVGen = CShaderStandard::UVGEN_ENVMAPPING; layerInfo.uMapChannel = 0; layerInfo.v3ScrollSpeed = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3RotationSpeed = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3ScrollOffset = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3RotationOffset = CVector3(0.0f, 0.0f, 0.0f); } else { if(i == 0) { LOG.Write("\n No diffuse. Skipping."); break; } continue; } if(!m_bPreview && m_bCopyTextures && m_strTexturePath != "") { for(int nTex = 0; nTex != vecTextures.size(); nTex++) { // Copy textures into the specified folder std::string strDestPath = m_strTexturePath; if(strDestPath[strDestPath.length() - 1] != '\\') { strDestPath.append("\\", 1); } strDestPath.append(vecTextures[nTex]); if(!CopyFile(vecPaths[nTex].data(), strDestPath.data(), FALSE)) { CLogger::NotifyWindow("Unable to copy %s to\n%s", vecPaths[i], strDestPath.data()); } } } if(layerInfo.eUVGen == CShaderStandard::UVGEN_ENVMAPPING && i == 1) { CLogger::NotifyWindow("%s : Bump with spheremapping not supported", pShaderStd->GetName().data()); } else { // Add layer switch(i) { case 0: pShaderStd->SetLayer(CShaderStandard::LAYER_DIFF, layerInfo); break; case 1: pShaderStd->SetLayer(CShaderStandard::LAYER_BUMP, layerInfo); break; case 2: pShaderStd->SetLayer(CShaderStandard::LAYER_MAP2, layerInfo); break; } } } // ¿Do we need blending? if(ARE_EQUAL(fAlpha, 1.0f) && !bDiffuseMap32Bits) { pShaderStd->SetBlendSrcFactor(UtilGL::States::BLEND_ONE); pShaderStd->SetBlendDstFactor(UtilGL::States::BLEND_ZERO); } else { pShaderStd->SetBlendSrcFactor(UtilGL::States::BLEND_SRCALPHA); pShaderStd->SetBlendDstFactor(UtilGL::States::BLEND_INVSRCALPHA); } // Add shader m_vecShaders.push_back(pShaderStd); } return true; }
// --[ Method ]--------------------------------------------------------------- // // - Class : CStravaganzaMaxTools // // - prototype : int BuildPhysiqueData(INode* pMaxNode, // CObject* pObject, // std::vector<std::string> &vecBoneNames, // std::vector<CBlendedVertex> &vecBlendedVertices) // // - Purpose : Builds the bone data for a given node. Returns the number // of bones processed (0 = failure). // // ----------------------------------------------------------------------------- int CStravaganzaMaxTools::BuildPhysiqueData(INode* pMaxNode, CObject* pObject, std::vector<std::string> &vecBoneNames, std::vector<CBlendedVertex> &vecBlendedVertices) { int nCount = 0; int nBoneCount = 0; Modifier *pPhyModifier = NULL; // Physique modifier IPhysiqueExport *pPhyExport = NULL; // Physique export interface IPhyContextExport *pPhyObjExport = NULL; // Physique object export interface vecBoneNames.clear(); vecBlendedVertices.clear(); // Build bone list std::vector<INode*> vecMaxBones; if(!AddNodeBones(vecMaxBones, pMaxNode)) { LOG.Write("\nWARNING - Error building node %s bone list", pMaxNode->GetName()); return 0; } // Build bones name list for(nBoneCount = 0; nBoneCount < vecMaxBones.size(); nBoneCount++) { vecBoneNames.push_back(vecMaxBones[nBoneCount]->GetName()); } // Get Physique modifier if(pPhyModifier = GetPhysiqueModifier(pMaxNode)) { pPhyExport = (IPhysiqueExport *)pPhyModifier->GetInterface(I_PHYINTERFACE); if(pPhyExport == NULL) { LOG.Write("\nWARNING - Couldn't get Physique export interface.\nFailed with node %s.", pMaxNode->GetName()); return 0; } } // Get physique object export interface pPhyObjExport = pPhyExport->GetContextInterface(pMaxNode); if(pPhyObjExport == NULL) { pPhyModifier->ReleaseInterface(I_PHYINTERFACE, pPhyExport); LOG.Write("\nWARNING - Unable to get physique context export.\nFailed with node %s.", pMaxNode->GetName()); return 0; } // Convert to rigid for time independent vertex assignment // Allow blending to export multi-link assignments pPhyObjExport->ConvertToRigid(true); pPhyObjExport->AllowBlending(true); // Build deformable vertex list bool bOK = true; int nBlendedCount = 0, nBlendedRigidCount = 0, nFloatingCount = 0; for(nCount = 0; nCount < pPhyObjExport->GetNumberVertices(); nCount++) { IPhyVertexExport *pPhyVertExport; IPhyBlendedRigidVertex *pPhyBRVertexExport; IPhyRigidVertex *pPhyRigidVertexExport; IPhyFloatingVertex *pPhyFloatingVertex; pPhyVertExport = pPhyObjExport->GetVertexInterface(nCount); CBlendedVertex blendedVertex; float fTotalWeight = 0.0f; bool bFloatingBones = false; // Floating Vertex pPhyFloatingVertex = pPhyObjExport->GetFloatingVertexInterface(nCount); if(pPhyFloatingVertex) { bFloatingBones = true; CVector3 v3OffsetVector; float fWeight; // More than one bone int nNumVtxBones = pPhyFloatingVertex->GetNumberNodes(); // LOG.Write("\n%u - Floating, with %u bones", nCount, nNumVtxBones); for(nBoneCount = 0; nBoneCount < nNumVtxBones; nBoneCount++) { int nIndex = GetBoneIndex(vecMaxBones, pPhyFloatingVertex->GetNode(nBoneCount)); if(nIndex == -1) { LOG.Write("\nWARNING - Unable to get bone index (%s)", pPhyFloatingVertex->GetNode(nBoneCount)->GetName()); bOK = false; break; } float fTotal; v3OffsetVector = Point3ToVector3(pPhyFloatingVertex->GetOffsetVector(nBoneCount)); fWeight = pPhyFloatingVertex->GetWeight(nBoneCount, fTotal); fTotalWeight += fWeight;//fTotal; //fWeight = fTotal; // LOG.Write("\n Weight = %f (%s)", fWeight, pPhyFloatingVertex->GetNode(nBoneCount)->GetName()); blendedVertex.AddLink(v3OffsetVector, nIndex, fWeight); } // LOG.Write("\n Total = %f", fTotalWeight); if(!ARE_EQUAL(fTotalWeight, 1.0f)) { LOG.Write("\n WARNING - Vertex %u has total weights %f", nCount, fTotalWeight); } nFloatingCount++; pPhyObjExport->ReleaseVertexInterface(pPhyFloatingVertex); } if(pPhyVertExport) { if(pPhyVertExport->GetVertexType() & BLENDED_TYPE) { CVector3 v3OffsetVector; float fWeight; // More than one bone pPhyBRVertexExport = (IPhyBlendedRigidVertex *)pPhyVertExport; int nNumVtxBones = pPhyBRVertexExport->GetNumberNodes(); // LOG.Write("\n%u - Blended, with %u bones", nCount, nNumVtxBones); for(nBoneCount = 0; nBoneCount < nNumVtxBones; nBoneCount++) { int nIndex = GetBoneIndex(vecMaxBones, pPhyBRVertexExport->GetNode(nBoneCount)); if(nIndex == -1) { LOG.Write("\nWARNING - Unable to get bone index (%s)", pPhyBRVertexExport->GetNode(nBoneCount)->GetName()); bOK = false; break; } v3OffsetVector = Point3ToVector3(pPhyBRVertexExport->GetOffsetVector(nBoneCount)); fWeight = pPhyBRVertexExport->GetWeight(nBoneCount); fTotalWeight += fWeight; // LOG.Write("\n Weight = %f (%s)", fWeight, pPhyBRVertexExport->GetNode(nBoneCount)->GetName()); blendedVertex.AddLink(v3OffsetVector, nIndex, fWeight); } // LOG.Write("\n Total = %f", fTotalWeight); if(!ARE_EQUAL(fTotalWeight, 1.0f)) { LOG.Write("\n WARNING - Vertex %u has total weights %f", nCount, fTotalWeight); } nBlendedCount++; } else { CVector3 v3OffsetVector; float fWeight; // Single bone pPhyRigidVertexExport = (IPhyRigidVertex *)pPhyVertExport; int nIndex = GetBoneIndex(vecMaxBones, pPhyRigidVertexExport->GetNode()); if(nIndex == -1) { LOG.Write("\nWARNING - Unable to get bone index (%s)", pPhyRigidVertexExport->GetNode()->GetName()); bOK = false; break; } v3OffsetVector = Point3ToVector3(pPhyRigidVertexExport->GetOffsetVector()); fWeight = 1.0f; fTotalWeight = 1.0f; // LOG.Write("\n%u - Rigid (%s)", nCount, pPhyRigidVertexExport->GetNode()->GetName()); blendedVertex.AddLink(v3OffsetVector, nIndex, fWeight); nBlendedRigidCount++; } pPhyObjExport->ReleaseVertexInterface(pPhyVertExport); } for(int i = 0; i < blendedVertex.GetNumLinks(); i++) { // Normalize blendedVertex.SetWeight(i, blendedVertex.GetWeight(i) / fTotalWeight); } vecBlendedVertices.push_back(blendedVertex); } pPhyExport->ReleaseContextInterface(pPhyObjExport); pPhyModifier->ReleaseInterface(I_PHYINTERFACE, pPhyExport); if(!bOK) { vecMaxBones.clear(); vecBoneNames.clear(); vecBlendedVertices.clear(); } else { LOG.Write("\nPhysique: %u bones, %u vertices (%u rigid, %u rigidblended, %u floating)", vecBoneNames.size(), vecBlendedVertices.size(), nBlendedRigidCount, nBlendedCount, nFloatingCount); } return vecMaxBones.size(); }
// --[ Method ]--------------------------------------------------------------- // // - Class : CMatrix // // - prototype : bool IsIdentity() const // // - Purpose : Returns true if matrix is the identity. // Use only if it avoids some computationally intense path. // // ----------------------------------------------------------------------------- bool CMatrix::IsIdentity() const { return (ARE_EQUAL(m_fM[0][0], 1.0f) && ARE_EQUAL(m_fM[1][1], 1.0f) && ARE_EQUAL(m_fM[2][2], 1.0f) && ARE_EQUAL(m_fM[3][3], 1.0f)) && (ARE_EQUAL(m_fM[0][1], 0.0f) && ARE_EQUAL(m_fM[0][2], 0.0f) && ARE_EQUAL(m_fM[0][3], 0.0f) && ARE_EQUAL(m_fM[1][0], 0.0f) && ARE_EQUAL(m_fM[1][2], 0.0f) && ARE_EQUAL(m_fM[1][3], 0.0f) && ARE_EQUAL(m_fM[2][0], 0.0f) && ARE_EQUAL(m_fM[2][1], 0.0f) && ARE_EQUAL(m_fM[2][3], 0.0f) && ARE_EQUAL(m_fM[3][0], 0.0f) && ARE_EQUAL(m_fM[3][1], 0.0f) && ARE_EQUAL(m_fM[3][2], 0.0f)); }