void Game_Update() { // calculate a spinning world matrix MFMatrix world; world.SetTranslation(MakeVector(0, -5, 50)); static float rotation = 0.0f; rotation += MFSystem_TimeDelta(); world.RotateY(rotation); // set world matrix to the model MFModel_SetWorldMatrix(pModel, world); // advance the animation MFAnimation *pAnim = MFModel_GetAnimation(pModel); if(pAnim) { float start, end; MFAnimation_GetFrameRange(pAnim, &start, &end); static float time = 0.f; time += MFSystem_TimeDelta();// * 500; while(time >= end) time -= end; MFAnimation_SetFrame(pAnim, time); } }
void EditorScreen::Draw() { GHScreen::DrawScreens(); MFRenderer_ClearScreen(MFRCF_Depth); MFMatrix mat; mat.LookAt(MakeVector(2.0,1.5,-1.0), MakeVector(1.0,0.3f,1.0f)); MFView_SetCameraMatrix(mat); // pScene->Draw(); }
void Fretboard::HitNote(int note) { float fretboardWidth = 7.0f; float columnWidth = fretboardWidth / 5.0f; float halfFB = fretboardWidth*0.5f; MFMatrix mat; mat.SetTranslation(MakeVector(-halfFB + (float)note*columnWidth + columnWidth*0.5f, 0.f, 0.f)); MFParticleSystem_SetWorldMatrix(pEmitter, mat); MFParticleSystem_BurstEmit(pEmitter, 100); }
void Game_Update() { static float rotation = 0.0f; rotation += MFSystem_GetTimeDelta(); // spin the prism MFMatrix world; world.SetTranslation(MakeVector(0, 0.3f, 3)); world.RotateY(rotation * 2.3f); MFStateBlock_SetMatrix(pPrismStateBlock, MFSCM_World, world); // spin the box world.SetTranslation(MakeVector(0, 0, 5)); world.RotateYPR(rotation, rotation * 2.0f, rotation * 0.5f); MFStateBlock_SetMatrix(pBoxStateBlock, MFSCM_World, world); }
void MFMat_Standard_CreateInstancePlatformSpecific(MFMaterial *pMaterial) { MFMat_Standard_Data_D3D11 *pData = (MFMat_Standard_Data_D3D11*)pMaterial->pInstanceData; MFMatrix mat = pData->textureMatrix; mat.Transpose(); pData->cbMaterial.mTexMatrix[0] = mat.GetXAxis(); pData->cbMaterial.mTexMatrix[1] = mat.GetYAxis(); pData->cbMaterial.vMeshColour = MFVector::white; pData->cbMaterial.gModelColour = MFVector::white; pData->cbMaterial.gColourMask = MakeVector(1.0f, 0.0f, 1.0f, 0.0f); D3D11_BUFFER_DESC desc; MFZeroMemory(&desc, sizeof(desc)); desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.ByteWidth = sizeof(pData->cbMaterial); desc.Usage = D3D11_USAGE_DEFAULT; //desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; g_pd3dDevice->CreateBuffer(&desc, NULL, &pData->pConstantBuffer); MFRenderer_D3D11_SetDebugName(pData->pConstantBuffer, pMaterial->pName); }
void MFRendererXB_SetTextureMatrix(const MFMatrix &textureMatrix) { MFMatrix texMat = textureMatrix; texMat.SetZAxis3(texMat.GetTrans()); pd3dDevice->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX*)&texMat); }
void Game_Draw() { MFCALLSTACK; MFRenderer_SetClearColour(0.f, 0.f, 0.2f, 1.f); MFRenderer_ClearScreen(); // Set identity camera (no camera) MFView_Push(); MFView_SetAspectRatio(MFDisplay_GetNativeAspectRatio()); MFView_SetProjection(); MFMaterial_SetMaterial(MFMaterial_GetStockMaterial(MFMat_White)); // set the world matrix to identity MFMatrix world = MFMatrix::identity; // move the box into the scene (along the z axis) world.Translate(MakeVector(0, 0, 5)); // increment rotation static float rotation = 0.0f; rotation += MFSystem_TimeDelta(); // rotate the box world.RotateYPR(rotation, rotation * 2.0f, rotation * 0.5f); // begin rendering the box MFPrimitive(PT_TriList); MFSetMatrix(world); // begin rendering 12 triangles (12 * 3 vertices) MFBegin(3 * 12); // draw a bunch of triangles MFSetColour(1,0,0,1); MFSetPosition(-1,-1, -1); MFSetPosition(-1, 1, -1); MFSetPosition( 1, 1, -1); MFSetPosition(-1,-1, -1); MFSetPosition( 1, 1, -1); MFSetPosition( 1,-1, -1); MFSetColour(0,1,0,1); MFSetPosition(-1,-1,1); MFSetPosition( 1,-1,1); MFSetPosition( 1, 1,1); MFSetPosition(-1,-1,1); MFSetPosition( 1, 1,1); MFSetPosition(-1, 1,1); MFSetColour(0,0,1,1); MFSetPosition( 1,-1,1); MFSetPosition( 1,-1,-1); MFSetPosition( 1, 1,-1); MFSetPosition( 1,-1,1); MFSetPosition( 1, 1,-1); MFSetPosition( 1, 1,1); MFSetColour(1,0,1,1); MFSetPosition(-1,-1,1); MFSetPosition(-1, 1,1); MFSetPosition(-1, 1,-1); MFSetPosition(-1,-1,1); MFSetPosition(-1, 1,-1); MFSetPosition(-1,-1,-1); MFSetColour(1,1,0,1); MFSetPosition(-1, 1,1); MFSetPosition( 1, 1,1); MFSetPosition( 1, 1,-1); MFSetPosition(-1, 1,1); MFSetPosition( 1, 1,-1); MFSetPosition(-1, 1,-1); MFSetColour(0,1,1,1); MFSetPosition(-1,-1,1); MFSetPosition(-1,-1,-1); MFSetPosition( 1,-1,-1); MFSetPosition(-1,-1,1); MFSetPosition( 1,-1,-1); MFSetPosition( 1,-1,1); MFEnd(); MFRect disp; MFDisplay_GetDisplayRect(&disp); MFView_SetOrtho(&disp); pUI->Draw(); MFView_Pop(); }
void Game_Update() { if(!bShowModel) { if(MFInput_WasPressed(Key_Up, IDD_Keyboard) && menuIndex > 0) --menuIndex; else if(MFInput_WasPressed(Key_Down, IDD_Keyboard) && menuIndex < (int)models.size()-1) ++menuIndex; else if(MFInput_WasPressed(Key_Return, IDD_Keyboard) && models.size() > 0) { bShowModel = true; // load model pModel = MFModel_CreateWithAnimation(models[menuIndex].CStr()); } } else { if(MFInput_WasPressed(Key_Escape, IDD_Keyboard)) { if(pModel) { MFModel_Destroy(pModel); pModel = NULL; } models.clear(); Scan("data:"); if(models.size() <= (size_t)menuIndex) menuIndex = models.size() ? (int)models.size() - 1 : 0; bShowModel = false; return; } if(pModel) { if(MFInput_Read(Mouse_LeftButton, IDD_Mouse) > 0.f) { yaw += -MFInput_Read(Mouse_XDelta, IDD_Mouse) * 0.02f; pitch += -MFInput_Read(Mouse_YDelta, IDD_Mouse) * 0.015f; } if(MFInput_Read(Mouse_MiddleButton, IDD_Mouse) > 0.f) { zoom *= 1.f + -MFInput_Read(Mouse_YDelta, IDD_Mouse) * 0.02f; } // calculate a spinning world matrix MFMatrix world; world.SetTranslation(MakeVector(0, -0.25f, 1) * zoom); world.RotateY(yaw); world.RotateX(pitch); // set world matrix to the model MFModel_SetWorldMatrix(pModel, world); // advance the animation MFAnimation *pAnim = MFModel_GetAnimation(pModel); if(pAnim) { float start, end; MFAnimation_GetFrameRange(pAnim, &start, &end); static float time = 0.f; time += MFSystem_TimeDelta();// * 500; while(time >= end) time -= end; MFAnimation_SetFrame(pAnim, time); } } } }
MFMatrix& MFMatrix::Scale(const MFVector& scale) { MFMatrix mat; mat.SetScale(scale); return Multiply(mat); }
MFMatrix& MFMatrix::RotateZ(float angle) { MFMatrix rot; rot.SetRotationZ(angle); return Multiply3x3(rot); }
MFMatrix& MFMatrix::RotateYPR(float yaw, float pitch, float roll) { MFMatrix mat; mat.SetRotationYPR(yaw, pitch, roll); return Multiply(mat, *this); }
MFMatrix& MFMatrix::RotateQ(const MFQuaternion &q) { MFMatrix mat; mat.SetRotationQ(q); return Multiply(mat, *this); }
MFMatrix& MFMatrix::Rotate(const MFVector &axis, float angle) { MFMatrix mat; mat.SetRotation(axis, angle); return Multiply(mat, *this); }
const char *ParseFrame(const char *pText, const MFMatrix &mat, int parentID) { char frameName[64]; const char *pName = GetNextToken(pText, &pText, frameName); MFMatrix worldMatrix = mat; F3DBone *pBone = NULL; if(!MFString_CaseCmpN(pName, "bn_", 3) || !MFString_CaseCmpN(pName, "z_", 2)) { int boneID = pModel->GetSkeletonChunk()->bones.size(); pBone = &pModel->GetSkeletonChunk()->bones[boneID]; F3DBone *pParent = parentID == -1 ? NULL : &pModel->GetSkeletonChunk()->bones[parentID]; parentID = boneID; MFString_Copy(pBone->name, pName); MFString_Copy(pBone->parentName, pParent ? pParent->name : ""); pBone->worldMatrix = mat; } if(MFString_Compare(pName, "{")) SkipToken(pText, "{"); const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "Frame")) { pText = ParseFrame(pText, worldMatrix, parentID); } else if(!MFString_Compare(pTok, "FrameTransformMatrix")) { SkipToken(pText, "{"); MFMatrix localMatrix; GetFloatArray(pText, (float*)&localMatrix, 16, &pText); worldMatrix.Multiply(localMatrix, worldMatrix); if(pBone) { pBone->boneMatrix = localMatrix; pBone->worldMatrix = worldMatrix; } SkipToken(pText, ";"); SkipToken(pText, "}"); } else if(!MFString_Compare(pTok, "Mesh")) { gMeshChunks.push(XMeshChunk::Create(worldMatrix, pText, pName)); SkipSection(pText); } else { MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } return pText; }
MF_API void MFParticleSystem_AddParticle(MFParticleEmitter *pEmitter) { MFParticleEmitterParameters *pE = &pEmitter->params; MFParticleSystem *pParticleSystem = pE->pParticleSystem; MFParticle *pNew = NULL; if(pParticleSystem->particles.GetLength() < pParticleSystem->params.maxActiveParticles) pNew = pParticleSystem->particles.Create(); if(pNew) { MFParticleParameters *pP = &pParticleSystem->params; pNew->colour = pP->colour; pNew->life = pP->life; pNew->rot = 0.0f; pNew->size = pP->size; switch(pE->type) { case MFET_Point: pNew->pos = pE->position.GetTrans(); break; case MFET_Sphere: case MFET_Disc: { MFVector offset; do { offset = MakeVector(MFRand_Range(-pE->radius, pE->radius), MFRand_Range(-pE->radius, pE->radius), MFRand_Range(-pE->radius, pE->radius)); } while(offset.MagSquared3() > pE->radius*pE->radius); if(pE->type == MFET_Disc) { // flatten it on to the disc float dist = offset.Dot3(pE->position.GetYAxis()); offset -= pE->position.GetYAxis()*dist; } pNew->pos = pE->position.GetTrans() + offset; break; } } switch(pE->behaviour) { case MFEB_Direction: pNew->velocity.Normalise3(pE->startVector); break; case MFEB_TargetAttract: pNew->velocity.Normalise3(pE->startVector - pE->position.GetTrans()); break; case MFEB_TargetRepel: pNew->velocity.Normalise3(pE->position.GetTrans() - pE->startVector); break; } pNew->velocity *= pE->velocity + MFRand_Range(-pE->velocityScatter, pE->velocityScatter); if(pE->directionScatter) { MFVector scatter; do { scatter = MakeVector(MFRand_Range(-1, 1), MFRand_Range(-1, 1), MFRand_Range(-1, 1)); float dist = scatter.Dot3(pE->position.GetYAxis()); scatter -= pE->position.GetYAxis()*dist; } while(scatter.MagSquared3() < 0.000001f); scatter.Normalise3(); MFMatrix scatterMat; scatterMat.SetRotation(scatter, MFRand_Unit()*pE->directionScatter); pNew->velocity = ApplyMatrixH(pNew->velocity, scatterMat); } } }
void CPUSkinningAlgorithm::transformGeometry( SkinnedGeometry *skinGeo, Skeleton *skel, CPUSkinningDataAttachment *data) { const SkinnedGeometry::MFPropIndicesType *mfOrigIdx = skinGeo->getMFPropIndices(); const SkinnedGeometry::MFPropertiesType *mfOrigProps = skinGeo->getMFProperties(); SkinnedGeometry::MFPropertiesType *mfProps = data->editMFProperties(); const GeoVec4fProperty *jointIdxProp = dynamic_cast<const GeoVec4fProperty *>( (*mfOrigProps)[skinGeo->getJointIndexProperty()]); const GeoVec4fProperty *jointWeightProp = dynamic_cast<const GeoVec4fProperty *>( (*mfOrigProps)[skinGeo->getJointWeightProperty()]); if(skinGeo->getIndex(skinGeo->getJointIndexProperty ()) != skinGeo->getIndex(skinGeo->getJointWeightProperty()) ) { SWARNING << "CPUSkinningAlgorithm::transformGeometry: " << "Multi indexed geometry not supported!" << std::endl; return; } mfProps->resize(mfOrigProps->size(), NULL); const MFMatrix *mfJointMat = NULL; const MFMatrix *mfJointNormalMat = NULL; // if the geometry has a non-identity bind shape matrix // premultiply joint matrices with bind shape matrix and store in data // attachment if(skinGeo->getBindShapeMatrix().equals(Matrix::identity(), Eps) == false) { mfJointMat = skel->getMFJointMatrices (); MFMatrix *mfJointBindMat = data->editMFJointMatrices(); mfJointBindMat->resize(mfJointMat->size()); for(UInt32 i = 0; i < mfJointMat->size(); ++i) { (*mfJointBindMat)[i] = (*mfJointMat)[i]; (*mfJointBindMat)[i].mult(skinGeo->getBindShapeMatrix()); } mfJointMat = data->getMFJointMatrices(); if(skel->getCalcNormalMatrices() == true) { mfJointNormalMat = skel->getMFJointNormalMatrices (); MFMatrix *mfJointNormalBindMat = data->editMFJointNormalMatrices(); mfJointNormalBindMat->resize(mfJointNormalMat->size()); for(UInt32 i = 0; i < mfJointNormalMat->size(); ++i) { (*mfJointNormalBindMat)[i] = (*mfJointNormalMat)[i]; (*mfJointNormalBindMat)[i].mult(skinGeo->getBindShapeMatrix()); } mfJointNormalMat = data->getMFJointNormalMatrices(); } else { mfJointNormalMat = data->getMFJointMatrices(); } } else { mfJointMat = skel->getMFJointMatrices(); if(skel->getCalcNormalMatrices() == true) { mfJointNormalMat = skel->getMFJointNormalMatrices(); } else { mfJointNormalMat = skel->getMFJointMatrices(); } } // transform all properties for(UInt16 i = 0; i < mfProps->size(); ++i) { // do not transform the vertex joint indices/weights if(i == skinGeo->getJointIndexProperty () || i == skinGeo->getJointWeightProperty() ) { continue; } GeoIntegralProperty *origPropIdx = (*mfOrigIdx )[i]; GeoVectorProperty *origProp = (*mfOrigProps)[i]; GeoVectorProperty *prop = (*mfProps )[i]; if(origProp == NULL) continue; if(prop == NULL) { GeoVectorPropertyUnrecPtr newProp = dynamic_pointer_cast<GeoVectorProperty>(origProp->clone()); mfProps->replace(i, newProp); prop = newProp; } else if(prop->size() != origProp->size()) { prop->resize(origProp->size()); } switch(origProp->getUsage() & GeoProperty::UsageSpaceMask) { case GeoProperty::UsageObjectSpace: { transformObjectSpaceProperty( mfJointMat, jointIdxProp, jointWeightProp, origPropIdx, origProp, prop); } break; case GeoProperty::UsageTangentSpace: { transformTangentSpaceProperty( mfJointNormalMat, jointIdxProp, jointWeightProp, origPropIdx, origProp, prop); } break; default: // only need to transform object/tangent space properties break; } } }
MF_API MFMatrix *MFAnimation_CalculateMatrices(MFAnimation *pAnimation, MFMatrix *pLocalToWorld) { MFAnimationBone *pAnims = pAnimation->pTemplate->pBones; MFModelBone *pBones = pAnimation->pBones; MFMatrix *pMats = pAnimation->pMatrices; float t = pAnimation->blendLayer.frameTime; MFDebug_Assert(t >= pAnimation->pTemplate->startTime && t <= pAnimation->pTemplate->endTime, "Frame time outside animation range..."); // find the frame number for each bone for(uint32 a=0; a<pAnimation->numBones; a++) { int map = pAnimation->pBoneMap[a]; if(map != -1) { float *pTimes = pAnims[map].pTime; int lastFrames = pAnims[map].numFrames-1; if(t == pTimes[lastFrames]) { pAnimation->blendLayer.pCurFrames[a].tweenStart = lastFrames; pAnimation->blendLayer.pCurFrames[a].tweenEnd = lastFrames; pAnimation->blendLayer.pCurFrames[a].tween = 0; } else { // TODO: change this to a binary search... for(int b=0; b<lastFrames; b++) { float t1 = pTimes[b]; float t2 = pTimes[b+1]; if(t >= pTimes[b] && t < pTimes[b+1]) { pAnimation->blendLayer.pCurFrames[a].tweenStart = b; pAnimation->blendLayer.pCurFrames[a].tweenEnd = b+1; pAnimation->blendLayer.pCurFrames[a].tween = (t-t1) / (t2-t1); break; } } } } } // calculate the matrix for each bone for(uint32 a=0; a<pAnimation->numBones; a++) { int map = pAnimation->pBoneMap[a]; if(map != -1) { MFMatrix &m1 = pAnims[map].pFrames[pAnimation->blendLayer.pCurFrames[a].tweenStart].key; MFMatrix &m2 = pAnims[map].pFrames[pAnimation->blendLayer.pCurFrames[a].tweenEnd].key; gWorkingMats[a].Tween(m1, m2, pAnimation->blendLayer.pCurFrames[a].tween); } else { gWorkingMats[a] = pBones[a].boneMatrix; } } // build the animation matrix for each bone... // TODO: this could be much faster for(uint32 a=0; a<pAnimation->numBones; a++) { MFMatrix boneMat = MFMatrix::identity; int b = (int)a; do { boneMat.Multiply(gWorkingMats[b]); b = pBones[b].parent; } while(b != -1); // pMats[a].Multiply(boneMat, pBones[a].invWorldMatrix); pMats[a].Multiply(pBones[a].invWorldMatrix, boneMat); if(pLocalToWorld) pMats[a].Multiply(*pLocalToWorld); } return pAnimation->pMatrices; }
void Fretboard::Draw(float time, dBChart *pSong, int track) { MFCALLSTACKc; MFView_Push(); MFRect rect; MFView_GetViewport(&rect); float aspect = rect.width / rect.height; aspect = MFClamp(0.82f, aspect, 2.0f); MFView_SetAspectRatio(aspect); if(viewPoint == 0) { // incoming MFView_ConfigureProjection(MFDEGREES(65.0f)/aspect, 1.0f, 100.0f); // Setup the Camera in 3D space. MFMatrix cameraMatrix; MFVector start = MakeVector( 0, 8, 3 ); MFVector dir = MakeVector( 0, 5, -8 ); dir = (dir-start) * (1.0f/1.777777777f); cameraMatrix.LookAt(start + dir*aspect, MakeVector(0.0f, 0.0f, 5.0f)); MFView_SetCameraMatrix(cameraMatrix); } else if(viewPoint == 1) { // overhead MFView_ConfigureProjection(MFDEGREES(45.0f), 1.0f, 100.0f); /* float aspect = MFDisplay_GetNativeAspectRatio(); MFView_SetAspectRatio(aspect); MFRect projRect; projRect.y = 15; projRect.height = -30; projRect.x = -projRect.y * aspect; projRect.width = -projRect.height * aspect; MFView_SetOrtho(&projRect); */ // Setup the Camera in 3D space. MFMatrix cameraMatrix; cameraMatrix.LookAt(MakeVector(0, 30, 10), MakeVector(0, 0, 10), MakeVector(0, 0, 1)); MFView_SetCameraMatrix(cameraMatrix); } else if(viewPoint == 2) { // overhead MFView_ConfigureProjection(MFDEGREES(45.0f), 1.0f, 100.0f); /* float aspect = MFDisplay_GetNativeAspectRatio(); MFView_SetAspectRatio(aspect); MFRect projRect; projRect.y = 15; projRect.height = -30; projRect.x = -projRect.y * aspect; projRect.width = -projRect.height * aspect; MFView_SetOrtho(&projRect); */ // Setup the Camera in 3D space. MFMatrix cameraMatrix; cameraMatrix.LookAt(MakeVector(0, 20, 13), MakeVector(0, 0, 13), MakeVector(-1, 0, 0)); MFView_SetCameraMatrix(cameraMatrix); } MFView_SetProjection(); MFMaterial *pFB = pSong->pFretboard ? pSong->pFretboard : pFretboard; MFMaterial_SetMaterial(pFB); MFPrimitive(PT_TriStrip, 0); int start = -4; int end = 60; int fadeStart = end - 10; float fretboardRepeat = 15.0f; float fretboardWidth = 7.0f; float columnWidth = fretboardWidth / 5.0f; float ringBorder = 0.1f; // draw the fretboard... MFBegin(((end-start) / 4) * 2 + 2); MFSetColourV(MFVector::white); float halfFB = fretboardWidth*0.5f; float offset = time*scrollSpeed; float topTime = time + end/scrollSpeed; float bottomTime = time + start/scrollSpeed; int a; float textureOffset = fmodf(offset, fretboardRepeat); for(a=start; a<end; a+=4) { float z = (float)a; MFSetTexCoord1(1.0f, 1.0f - (z+textureOffset) / fretboardRepeat); MFSetPosition(halfFB, 0.0f, z); MFSetTexCoord1(0.0f, 1.0f - (z+textureOffset) / fretboardRepeat); MFSetPosition(-halfFB, 0.0f, z); } float z = (float)a; MFSetTexCoord1(1.0f, 1.0f - (z+textureOffset) / fretboardRepeat); MFSetPosition(halfFB, 0.0f, z); MFSetTexCoord1(0.0f, 1.0f - (z+textureOffset) / fretboardRepeat); MFSetPosition(-halfFB, 0.0f, z); MFEnd(); // draw the selection region MFMaterial_SetMaterial(pFrets); MFPrimitive(PT_TriStrip, 0); if(gEditor.selectStart != gEditor.selectEnd) { float selectStartTime = GETSECONDS(pSong->CalculateTimeOfTick(gEditor.selectStart)); float selectEndTime = GETSECONDS(pSong->CalculateTimeOfTick(gEditor.selectEnd)); if(selectStartTime < topTime && selectEndTime > bottomTime) { selectStartTime = (MFMax(bottomTime, selectStartTime) - time) * scrollSpeed; selectEndTime = (MFMin(topTime, selectEndTime) - time) * scrollSpeed; MFBegin(4); MFSetColour(1.0f, 0.0f, 0.0f, 0.5f); MFSetPosition(-halfFB, 0.0f, selectEndTime); MFSetPosition(halfFB, 0.0f, selectEndTime); MFSetPosition(-halfFB, 0.0f, selectStartTime); MFSetPosition(halfFB, 0.0f, selectStartTime); MFEnd(); } } // draw the fretboard edges and bar lines const float barWidth = 0.2f; MFMaterial_SetMaterial(pBar); MFPrimitive(PT_TriStrip, 0); MFBegin(4); MFSetColour(0.0f, 0.0f, 0.0f, 0.8f); MFSetTexCoord1(0,0); MFSetPosition(-halfFB, 0.0f, barWidth); MFSetTexCoord1(1,0); MFSetPosition(halfFB, 0.0f, barWidth); MFSetTexCoord1(0,1); MFSetPosition(-halfFB, 0.0f, -barWidth); MFSetTexCoord1(1,1); MFSetPosition(halfFB, 0.0f, -barWidth); MFEnd(); MFMaterial_SetMaterial(pEdge); MFPrimitive(PT_TriStrip, 0); MFBegin(34); MFSetColour(0.0f, 0.0f, 0.0f, 0.3f); for(int col=1; col<5; col++) { if(col > 1) MFSetPosition(-halfFB + columnWidth*(float)col - 0.02f, 0.0f, (float)end); MFSetTexCoord1(0,0); MFSetPosition(-halfFB + columnWidth*(float)col - 0.02f, 0.0f, (float)end); MFSetTexCoord1(1,0); MFSetPosition(-halfFB + columnWidth*(float)col + 0.02f, 0.0f, (float)end); MFSetTexCoord1(0,1); MFSetPosition(-halfFB + columnWidth*(float)col - 0.02f, 0.0f, (float)start); MFSetTexCoord1(1,1); MFSetPosition(-halfFB + columnWidth*(float)col + 0.02f, 0.0f, (float)start); MFSetPosition(-halfFB + columnWidth*(float)col + 0.02f, 0.0f, (float)start); } MFSetColourV(MFVector::white); MFSetPosition(-halfFB - 0.1f, 0.0f, (float)end); MFSetTexCoord1(0,0); MFSetPosition(-halfFB - 0.1f, 0.0f, (float)end); MFSetTexCoord1(1,0); MFSetPosition(-halfFB + 0.1f, 0.0f, (float)end); MFSetTexCoord1(0,1); MFSetPosition(-halfFB - 0.1f, 0.0f, (float)start); MFSetTexCoord1(1,1); MFSetPosition(-halfFB + 0.1f, 0.0f, (float)start); MFSetPosition(-halfFB + 0.1f, 0.0f, (float)start); MFSetPosition(halfFB - 0.1f, 0.0f, (float)end); MFSetTexCoord1(0,0); MFSetPosition(halfFB - 0.1f, 0.0f, (float)end); MFSetTexCoord1(1,0); MFSetPosition(halfFB + 0.1f, 0.0f, (float)end); MFSetTexCoord1(0,1); MFSetPosition(halfFB - 0.1f, 0.0f, (float)start); MFSetTexCoord1(1,1); MFSetPosition(halfFB + 0.1f, 0.0f, (float)start); MFEnd(); // draw the frets.... MFMaterial_SetMaterial(pBar); MFPrimitive(PT_TriStrip, 0); int bottomTick = pSong->CalculateTickAtTime((int64)(bottomTime*1000000.0f)); int res = pSong->GetRes(); int ticks = bHalfFrets ? res/2 : res; int fretBeat = bottomTick + ticks - 1; fretBeat -= fretBeat % ticks; float fretTime = GETSECONDS(pSong->CalculateTimeOfTick(fretBeat)); while(fretTime < topTime) { bool halfBeat = (fretBeat % res) != 0; bool bar = false; if(!halfBeat) { GHEvent *pLastTS = pSong->sync.GetMostRecentEvent(GHE_TimeSignature, fretBeat); if(pLastTS) bar = ((fretBeat - pLastTS->tick) % (pLastTS->parameter*res)) == 0; else if(fretBeat == 0) bar = true; } float bw = bar ? barWidth : barWidth*0.5f; MFBegin(4); float position = (fretTime - time) * scrollSpeed; if(!halfBeat) MFSetColourV(MFVector::white); else MFSetColourV(MakeVector(1,1,1,0.3f)); MFSetTexCoord1(0,0); MFSetPosition(-halfFB, 0.0f, position + bw); MFSetTexCoord1(1,0); MFSetPosition(halfFB, 0.0f, position + bw); MFSetTexCoord1(0,1); MFSetPosition(-halfFB, 0.0f, position + -bw); MFSetTexCoord1(1,1); MFSetPosition(halfFB, 0.0f, position + -bw); MFEnd(); fretBeat += ticks; fretTime = GETSECONDS(pSong->CalculateTimeOfTick(fretBeat)); } // draw the notes... GHEventManager ¬eStream = pSong->notes[track]; GHEvent *pEv = noteStream.First(); int64 topTimeus = (int64)(topTime*1000000.0f); while(pEv && pEv->time < topTimeus) { if((pEv->event == GHE_Note || pEv->event == GHE_Special) && pEv->tick + pEv->parameter >= bottomTick) { float evTime = GETSECONDS(pEv->time); // TODO: we need to calculate the end of the hold... float noteEnd = evTime; if(pEv->parameter) noteEnd = GETSECONDS(pSong->CalculateTimeOfTick(pEv->tick + pEv->parameter)); if(pEv->event == GHE_Note && pEv->played != 1) { // draw a note int key = pEv->key; bool tap = false; // check if there is a previous note, and it is in range if(pEv->Prev() && pEv->Prev()->tick < pEv->tick && pEv->Prev()->tick > pEv->tick - (res/2) && pEv->Prev()->key != pEv->key && (!pEv->Next() || !(pEv->Next()->tick == pEv->tick)) && !pEv->Prev()->parameter && !(pEv->Prev()->Prev() && pEv->Prev()->Prev()->tick == pEv->Prev()->tick)) { tap = true; } int noteX = gConfig.controls.leftyFlip[0] ? 4-key : key; float position = (GETSECONDS(pEv->time) - time)*scrollSpeed; float xoffset = -halfFB + columnWidth*0.5f + (float)noteX*columnWidth; if(pEv->parameter) { MFMaterial_SetMaterial(pFrets); float whammyTop = (noteEnd - time)*scrollSpeed; MFPrimitive(PT_TriStrip, 0); // TODO: we could consider not drawing this part of the hold line.. seems reasonable that it terminates at the line... if(gEditor.state == GHPS_Stopped) { if(position < 0.0f) { MFBegin(4); MFSetColourV(gColours[key]); MFSetPosition(xoffset - 0.2f, 0.0f, MFMin(whammyTop, 0.0f)); MFSetPosition(xoffset + 0.2f, 0.0f, MFMin(whammyTop, 0.0f)); MFSetPosition(xoffset - 0.2f, 0.0f, position); MFSetPosition(xoffset + 0.2f, 0.0f, position); MFEnd(); } } if(whammyTop > 0.0f) { // this half could have waves cruising down it if we wanted to support the whammy... MFBegin(4); MFSetColourV(gColours[key]); MFSetPosition(xoffset - 0.2f, 0.0f, MFMin(whammyTop, (float)end)); MFSetPosition(xoffset + 0.2f, 0.0f, MFMin(whammyTop, (float)end)); MFSetPosition(xoffset - 0.2f, 0.0f, MFMax(position, 0.0f)); MFSetPosition(xoffset + 0.2f, 0.0f, MFMax(position, 0.0f)); MFEnd(); } } if(evTime >= bottomTime) { MFMatrix mat; mat.SetScale(MakeVector(0.5f/20, 0.5f/20, 0.5f/20)); mat.Translate(MakeVector(xoffset, 0.03f, position)); MFModel_SetWorldMatrix(pButton, mat); MFStateBlock *pSB = MFStateBlock_CreateTemporary(64); MFStateBlock_SetVector(pSB, MFSCV_DiffuseColour, pEv->played == -1 ? MakeVector(0.3f, 0.3f, 0.3f, 1.0f) : MFVector::white); // MFStateBlock_SetVector(pSB, MFSCV_DiffuseColour, position < 0.0f ? MakeVector(0.3f, 0.3f, 0.3f, 1.0f) : MFVector::white); // MFRenderer_SetRenderStateOverride(MFRS_MaterialOverride, (uint32&)(tap ? pButtonMat[key] : pButtonRing[key])); MFRenderer_AddModel(pButton, pSB, MFView_GetViewState()); // render the note time if(bRenderNoteTimes) { MFView_Push(); MFView_SetOrtho(&rect); MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(xoffset, 0.0f, position), &pos); pos.x += 16.0f; pos.y -= 26.0f; int minutes = (int)(pEv->time / 60000000); int seconds = (int)((pEv->time % 60000000) / 1000000); int milliseconds = (int)((pEv->time % 1000000) / 1000); MFFont_DrawTextf(pText, pos, 20.0f, MFVector::yellow, "%s: %d:%02d.%d\nTick: %g", MFTranslation_GetString(pStrings, TRACK_TIME), minutes, seconds, milliseconds, (float)pEv->tick/res); MFView_Pop(); } } } if(pEv->event == GHE_Special) { // static MFVector specialColours[3] = { MakeVector(1,0,0,1), MakeVector(1,1,0,1), MakeVector(0,0,1,1) }; // static float specialX[3] = { halfFB + 0.2f, halfFB + 1, -halfFB - 1 }; // static float specialWidth[3] = { 0.8f, 0.8f, 0.8f }; static MFVector specialColours[3] = { MakeVector(1,0,0,0.5f), MakeVector(1,1,0,0.5f), MakeVector(0,0,1,0.5f) }; static float specialX[3] = { -halfFB, halfFB - 0.8f, -halfFB }; static float specialWidth[3] = { 0.8f, 0.8f, fretboardWidth }; float bottom = (evTime - time)*scrollSpeed; float top = (noteEnd - time)*scrollSpeed; int key = pEv->key; MFMaterial_SetMaterial(pFrets); MFPrimitive(PT_TriStrip, 0); MFBegin(4); MFSetColourV(specialColours[key]); MFSetPosition(specialX[key], 0.0f, MFMin(top, (float)end)); MFSetPosition(specialX[key]+specialWidth[key], 0.0f, MFMin(top, (float)end)); MFSetPosition(specialX[key], 0.0f, MFMax(bottom, (float)start)); MFSetPosition(specialX[key]+specialWidth[key], 0.0f, MFMax(bottom, (float)start)); MFEnd(); } } pEv = pEv->Next(); } // MFRenderer_SetRenderStateOverride(MFRS_MaterialOverride, NULL); // draw circles at the bottom.. MFMaterial_SetMaterial(pRing); for(int a=0; a<5; a++) { DrawRing(-halfFB + (float)a*columnWidth + columnWidth*ringBorder, 0.0f, columnWidth*(1.0f-ringBorder*2)); } for(int a=0; a<5; a++) { dBControlType keys_righty[] = { dBCtrl_Edit_Note0, dBCtrl_Edit_Note1, dBCtrl_Edit_Note2, dBCtrl_Edit_Note3, dBCtrl_Edit_Note4 }; dBControlType keys_lefty[] = { dBCtrl_Edit_Note4, dBCtrl_Edit_Note3, dBCtrl_Edit_Note2, dBCtrl_Edit_Note1, dBCtrl_Edit_Note0 }; dBControlType *keys = gConfig.controls.leftyFlip[0] ? keys_lefty : keys_righty; int ringPos = gConfig.controls.leftyFlip[0] ? 4-a : a; MFMaterial_SetMaterial(pColourRing[a]); DrawRing(-halfFB + (float)ringPos*columnWidth, 0.0f, columnWidth, !TestControl(keys[a], GHCT_Hold)); } // render trigger particles MFParticleSystem_Draw(pParticles); // render text and stuff MFView_SetOrtho(&rect); pEv = pSong->sync.GetNextEvent(bottomTick); while(pEv && pEv->time < topTimeus) { float evTime = GETSECONDS(pEv->time); if(evTime > bottomTime) { if(pEv->event == GHE_BPM) { float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(halfFB + 0.2f, 0.0f, position), &pos); pos.y -= 12.0f; MFFont_DrawTextf(pText, pos, 24.0f, MakeVector(0,0.5f,0,1), "%s: %g", MFTranslation_GetString(pStrings, TRACK_BPM), (float)pEv->parameter * 0.001f); } if(pEv->event == GHE_Anchor) { int minutes = (int)(pEv->time / 60000000); int seconds = (int)((pEv->time%60000000)/1000000); int milliseconds = (int)((pEv->time%1000000)/1000); float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(halfFB + 0.2f, 0.0f, position), &pos); pos.y -= 12.0f; MFFont_DrawTextf(pText, pos, 24.0f, MakeVector(0,0.5f,0,1), "A: %02d:%02d.%03d\n %s: %g", minutes, seconds, milliseconds, MFTranslation_GetString(pStrings, TRACK_BPM), (float)pEv->parameter * 0.001f); } else if(pEv->event == GHE_TimeSignature) { float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(-halfFB - 0.2f, 0.0f, position), &pos); const char *pString = MFStr("TS: %d/4", pEv->parameter); pos.x -= MFFont_GetStringWidth(pText, pString, 24.0f); pos.y -= 12.0f; MFFont_DrawTextf(pText, pos, 24.0f, MFVector::yellow, pString); } } pEv = pEv->Next(); } // render events pEv = pSong->events.GetNextEvent(bottomTick); int lastChecked = -1; float yEventOffset = -12.0f; while(pEv && pEv->time < topTimeus) { float evTime = GETSECONDS(pEv->time); if(evTime > bottomTime) { if(pEv->event == GHE_Event) { if(lastChecked != pEv->tick) { yEventOffset = -12.0f; lastChecked = pEv->tick; if(pSong->sync.FindEvent(GHE_TimeSignature, pEv->tick, 0)) { yEventOffset -= 24.0f; } } float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(-halfFB - 0.2f, 0.0f, position), &pos); if(!MFString_CompareN(pEv->GetString(), "section ", 8)) { // draw a line across? pos.x -= MFFont_GetStringWidth(pText, &pEv->GetString()[8], 24.0f); pos.y += yEventOffset; MFFont_DrawTextf(pText, pos, 24.0f, MFVector::blue, &pEv->GetString()[8]); } else { pos.x -= MFFont_GetStringWidth(pText, pEv->GetString(), 24.0f); pos.y += yEventOffset; MFFont_DrawTextf(pText, pos, 24.0f, MFVector::white, pEv->GetString()); } yEventOffset -= 24.0f; } } pEv = pEv->Next(); } // render track events pEv = pSong->notes[track].GetNextEvent(bottomTick); lastChecked = -1; yEventOffset = -12.0f; while(pEv && pEv->time < topTimeus) { float evTime = GETSECONDS(pEv->time); if(evTime > bottomTime) { if(pEv->event == GHE_Event) { if(lastChecked != pEv->tick) { yEventOffset = -12.0f; lastChecked = pEv->tick; if(pSong->sync.FindEvent(GHE_TimeSignature, pEv->tick, 0)) { yEventOffset -= 24.0f; } GHEvent *pOther = pSong->events.FindEvent(GHE_Event, pEv->tick, 0); while(pOther && pOther->tick == pEv->tick) { yEventOffset -= 24.0f; pOther = pOther->Next(); } } float position = (evTime - time) * scrollSpeed; MFVector pos; MFView_TransformPoint3DTo2D(MakeVector(-halfFB - 0.2f, 0.0f, position), &pos); pos.x -= MFFont_GetStringWidth(pText, pEv->GetString(), 24.0f); pos.y += yEventOffset; MFFont_DrawTextf(pText, pos, 24.0f, MakeVector(0.6f, 0.8f, 1.0f, 1.0f), pEv->GetString()); yEventOffset -= 24.0f; } } pEv = pEv->Next(); } MFView_Pop(); }