MF_API void MFView_TransformPoint3DTo2D(const MFVector& point, MFVector *pResult) { MFMatrix proj, viewProj, view; // get the perspective projection matrix proj.SetPerspective(pCurrentView->fov, pCurrentView->nearPlane, pCurrentView->farPlane, pCurrentView->aspectRatio); // in this special case, we'll make the projection matrix produce a 0-1 value in z across all platforms (some platforms project into different 'z' spaces) float zn = pCurrentView->nearPlane; float zf = pCurrentView->farPlane; float zd = zf-zn; float zs = zf/zd; proj.m[10] = zs; proj.m[14] = -zn*zs; // get the view matrix (which we will need to calculate if we are in ortho mode) if(!MFView_IsOrtho()) view = MFView_GetWorldToViewMatrix(); else view.Inverse(MFView_GetCameraMatrix()); viewProj.Multiply4x4(view, proj); // apply the projection and perform the perspective divide MFVector transformed; transformed = ApplyMatrix(point, viewProj); transformed *= MFRcp(transformed.w); // and shift the result into the ortho rect transformed.x += 1.0f; transformed.y = -transformed.y + 1.0f; *pResult = transformed * MakeVector(pCurrentView->orthoRect.width*0.5f, pCurrentView->orthoRect.height*0.5f) + MakeVector(pCurrentView->orthoRect.x, pCurrentView->orthoRect.y); }
MF_API const MFMatrix& MFView_GetWorldToScreenMatrix() { if(pCurrentView->viewProjDirty) { pCurrentView->viewProj.Multiply4x4(MFView_GetWorldToViewMatrix(), MFView_GetViewToScreenMatrix()); pCurrentView->viewProjDirty = false; } return pCurrentView->viewProj; }
MF_API void MFView_TransformPoint2DTo3D(const MFVector& point, MFVector *pResult, MFVector *pResultRayDir) { MFMatrix proj, viewProj, view; // get the perspective projection matrix proj.SetPerspective(pCurrentView->fov, pCurrentView->nearPlane, pCurrentView->farPlane, pCurrentView->aspectRatio); // in this special case, we'll make the projection matrix produce a 0-1 value in z across all platforms (some platforms project into different 'z' spaces) float zn = pCurrentView->nearPlane; float zf = pCurrentView->farPlane; float zd = zf-zn; float zs = zf/zd; proj.m[10] = zs; proj.m[14] = -zn*zs; // get the view matrix (which we will need to calculate if we are in ortho mode) if(!MFView_IsOrtho()) view = MFView_GetWorldToViewMatrix(); else view.Inverse(MFView_GetCameraMatrix()); viewProj.Multiply4x4(view, proj); // inverse projection viewProj.Inverse(); // which the point from ortho space back into homogeneous space *pResult = point; *pResult -= MakeVector(pCurrentView->orthoRect.x, pCurrentView->orthoRect.y); *pResult *= MakeVector(MFRcp(pCurrentView->orthoRect.width*0.5f), MFRcp(pCurrentView->orthoRect.height*0.5f)); pResult->x -= 1.0f; pResult->y = -pResult->y + 1.0f; // and un-project // TODO: undo the perspective divide (f**k) *pResult = ApplyMatrix(*pResult, viewProj); if(pResultRayDir) { // calculate the pixels rays direction.. } }
MF_API MFMatrix* MFView_GetLocalToView(const MFMatrix& localToWorld, MFMatrix *pOutput) { pOutput->Multiply4x4(localToWorld, MFView_GetWorldToViewMatrix()); return pOutput; }
MF_API void MFParticleSystem_Draw(MFParticleSystem *pParticleSystem) { int numParticles = pParticleSystem->particles.GetLength(); if(numParticles == 0) return; // render particles MFView_Push(); MFMatrix ltv = MFView_GetWorldToViewMatrix(); MFView_SetCameraMatrix(MFMatrix::identity); // update and draw each particle if(pParticleSystem->params.rotationRate != 0.0f) { MFParticleSystem_DrawRotating(pParticleSystem, ltv); MFView_Pop(); return; } float fadeStart = pParticleSystem->params.life - pParticleSystem->params.fadeDelay; MFMaterial_SetMaterial(pParticleSystem->pMaterial); MFPrimitive(PT_QuadList, 0); MFBegin(numParticles * 2); MFParticle **ppI = pParticleSystem->particles.Begin(); while(*ppI) { MFParticle *pParticle = *ppI; float dt = MFSystem_TimeDelta(); pParticle->size += pParticleSystem->params.scaleRate * dt; pParticle->velocity += pParticleSystem->params.force * dt; pParticle->pos += pParticle->velocity * dt; float halfSize = pParticle->size * 0.5f; float alpha = MFMin(pParticle->life / fadeStart, 1.0f); MFVector pos = ApplyMatrixH(pParticle->pos, ltv); MFSetColourV(MakeVector(pParticle->colour, pParticle->colour.w * alpha)); MFSetTexCoord1(0, 0); MFSetPosition(pos.x - halfSize, pos.y + halfSize, pos.z); MFSetTexCoord1(1, 1); MFSetPosition(pos.x + halfSize, pos.y - halfSize, pos.z); pParticle->life -= dt; if(pParticle->life < 0.0f) pParticleSystem->particles.Destroy(ppI); ppI++; } MFEnd(); MFView_Pop(); }