int VMobileForwardRenderLoop::GetLightInfluenceArea(VisLightSource_cl *pLight) { VASSERT(pLight != NULL); VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext(); int iScreenWidth,iScreenHeight; pContext->GetSize(iScreenWidth, iScreenHeight); if (pLight->GetType() == VIS_LIGHT_DIRECTED) { // directional lights influence the whole screen return (iScreenWidth*iScreenHeight); } hkvMat4 projMatrix = pContext->GetViewProperties()->getProjectionMatrix(hkvClipSpaceYRange::MinusOneToOne); hkvMat4 viewMatrix = pContext->GetCamera()->GetWorldToCameraTransformation(); // get position/ radius of bounding sphere hkvVec3 vPosition; float fRadius = 0.0f; if (pLight->GetType() == VIS_LIGHT_POINT) { vPosition = pLight->GetPosition(); fRadius = pLight->GetRadius(); } else if (pLight->GetType() == VIS_LIGHT_SPOTLIGHT) { hkvAlignedBBox bBox; pLight->GetBoundingBox(bBox); vPosition = bBox.getBoundingSphere().m_vCenter; fRadius = bBox.getBoundingSphere().m_fRadius; } else VASSERT_MSG(false, "Unsupported light type"); // get corners of bounding rectangle in view space hkvVec4 vPositionVS = viewMatrix*vPosition.getAsVec4(1.0f); hkvVec4 vCorners[4]; vCorners[0] = vPositionVS+hkvVec4(-fRadius, -fRadius, 0.0f, 0.0f); vCorners[1] = vPositionVS+hkvVec4(fRadius, -fRadius, 0.0f, 0.0f); vCorners[2] = vPositionVS+hkvVec4(fRadius, fRadius, 0.0f, 0.0f); vCorners[3] = vPositionVS+hkvVec4(-fRadius, fRadius, 0.0f, 0.0f); // get corners of bounding rectangle in normalized device coordinates for (int i=0;i<4;i++) { vCorners[i] = projMatrix*vCorners[i]; vCorners[i] /= vCorners[i].w; } // clip corners of bounding rectangle hkvVec2 vMin(vCorners[0].x, vCorners[0].y); vMin.clampTo(hkvVec2(-1.0f, -1.0f), hkvVec2(1.0f, 1.0f)); hkvVec2 vMax(vCorners[2].x, vCorners[2].y); vMax.clampTo(hkvVec2(-1.0f, -1.0f), hkvVec2(1.0f, 1.0f)); // calculate influence area int iWidth = (int)((vMax.x-vMin.x)*0.5f*iScreenWidth); int iHeight = (int)((vMax.y-vMin.y)*0.5f*iScreenHeight); return (iWidth*iHeight); }
void BoundingVolume::GetSplitAxis(const float *pointsPtr, unsigned int numPoints, Float3 &splitAxis, float &_min, float &_max) { Float3 vMin( FLT_MAX, FLT_MAX, FLT_MAX ); Float3 vMax( -FLT_MAX, -FLT_MAX, -FLT_MAX ); for(unsigned int i = 0; i < numPoints; i +=3 ) for(unsigned int j = 0; j < 3; ++j) { vMin.v[j] = min( vMin.v[j], pointsPtr[i+j] ); vMax.v[j] = max( vMax.v[j], pointsPtr[i+j] ); } unsigned int axis = 0; if( vMax.v[axis] - vMin.v[axis] < vMax.v[1] - vMin.v[1] ) axis = 1; if( vMax.v[axis] - vMin.v[axis] < vMax.v[2] - vMin.v[2] ) axis = 2; splitAxis.makeZero(); splitAxis.v[axis] = 1.0f; _min = vMin.v[axis]; _max = vMax.v[axis]; }
void SetupDispBoxes( const CCoreDispInfo *pListBase, int listSize, CUtlVector<CDispBox> &out ) { out.SetSize( listSize ); for ( int i=0; i < listSize; i++ ) { const CCoreDispInfo *pDisp = &pListBase[i]; // Calculate the bbox for this displacement. Vector vMin( 1e24, 1e24, 1e24 ); Vector vMax( -1e24, -1e24, -1e24 ); for ( int iVert=0; iVert < 4; iVert++ ) { const Vector &vTest = pDisp->GetSurface()->GetPoint( iVert ); VectorMin( vTest, vMin, vMin ); VectorMax( vTest, vMax, vMax ); } // Puff the box out a little. static float flPuff = 0.1f; vMin -= Vector( flPuff, flPuff, flPuff ); vMax += Vector( flPuff, flPuff, flPuff ); out[i].m_Min = vMin; out[i].m_Max = vMax; } }
void CPlayerCamera::Update( const FLOAT fFrameTime, BOOL bIsCurrent ) { VECTOR vSize = GetGameEngine()->GetView()->GetViewSize(); vSize = vSize; VECTOR vMin( 999999.9f, 999999.9f ); VECTOR vMax( -999999.9f, -999999.9f ); VECTOR vAvgPos( 0.0f, 0.0f ); UINT uCnt = 0; std::list<CActor*>::iterator it; for ( it = m_Actors.begin() ; it != m_Actors.end(); it++ ) { if ( !(*it)->IsDead() ) { VECTOR vPos = (*it)->GetPosition(); vAvgPos += vPos; uCnt++; vMin.x = Math::Min( vMin.x, vPos.x ); vMin.y = Math::Min( vMin.y, vPos.y ); vMax.x = Math::Max( vMax.x, vPos.x ); vMax.y = Math::Max( vMax.y, vPos.y ); } } if ( uCnt > 0 ) { vAvgPos = vAvgPos / (FLOAT)uCnt; VECTOR vBox = vMax - vMin; vBox *= 0.5f; FLOAT fScale = Math::Abs( Math::Max( vBox.x / vSize.x, vBox.y / vSize.y ) ) / 0.8f; if ( fScale > 1.0f ) { fScale = Math::Min( fScale, MAX_ZOOM ); m_fZoom = fScale; } else { m_fZoom = 1.0f ; } } else { vAvgPos = m_vLastPosition; } m_vLastPosition = vAvgPos; m_vScroll = vAvgPos - vSize; m_vScroll += m_vOffset; }
IFXRESULT CIFXMesh::CalcBoundingSphere() { IFXVector4 vMin(FLT_MAX, FLT_MAX, FLT_MAX, 0); IFXVector4 vMax(-FLT_MAX,-FLT_MAX,-FLT_MAX, 0); // Determine the axis aligned bounding box and the number of verticies. IFXVector3* vertex; IFXVector3Iter vIter; GetPositionIter(vIter); U32 i; for( i = m_uNumVertices; i--; ) { vertex = vIter.Next(); if ( vertex->X() < vMin.R() ) vMin.R() = vertex->X(); if ( vertex->X() > vMax.R() ) vMax.R() = vertex->X(); if ( vertex->Y() < vMin.G() ) vMin.G() = vertex->Y(); if ( vertex->Y() > vMax.G() ) vMax.G() = vertex->Y(); if ( vertex->Z() < vMin.B() ) vMin.B() = vertex->Z(); if ( vertex->Z() > vMax.B() ) vMax.B() = vertex->Z(); } // If there are any verticies, find the average position as the center, // and the distance to the furthest point as the radius. if ( m_uNumVertices ) { vMin.Add(vMax); vMin.Scale3(0.5f); m_vBoundingSphere = vMin; F32 fMaxSquaredDistance = -FLT_MAX; F32 fSquaredDistance; IFXVector3 d; GetPositionIter(vIter); U32 i; for( i = m_uNumVertices; i--; ) { vertex = vIter.Next(); d.X() = vertex->X() - m_vBoundingSphere.R(); d.Y() = vertex->Y() - m_vBoundingSphere.G(); d.Z() = vertex->Z() - m_vBoundingSphere.B(); fSquaredDistance = d.DotProduct(d); if ( fSquaredDistance > fMaxSquaredDistance ) fMaxSquaredDistance = fSquaredDistance; } m_vBoundingSphere.A() = sqrtf( fMaxSquaredDistance ); } else m_vBoundingSphere.Set( 0.0, 0.0, 0.0, 0.0 ); return IFX_OK; }
///////////////////////////////////////////////////////////////////////////// // Write data files for plotting 1D distribution ///////////////////////////////////////////////////////////////////////////// void CQLRIO::Distrib(CRegression ®, const std::string &sPrefix) { { std::ostringstream oss; oss << sPrefix << "MAP.dat"; std::ofstream ofs(oss.str().c_str()); CQLRIO::Plot(ofs, reg.GetPF(), reg.MAP()); } { std::ostringstream ossRandom; ossRandom << sPrefix << "random.dat"; std::ofstream ofs(ossRandom.str().c_str()); std::ostringstream ossMax; ossMax << sPrefix << "max.dat"; std::ofstream ofsMax(ossMax.str().c_str()); CRandom<unsigned> rnd; const int PosteriorSamples = 50; for (int i = PosteriorSamples; --i >= 0;) { std::vector<double> vParam(reg.GetPF().GetParameters()); // reg.GaussianSample(rnd, vParam); reg.MCMCSample(rnd, vParam, 20); if (reg.GetPF().GetDimensions() <= 1 || i < 5) { CQLRIO::Plot(ofs, reg.GetPF(), &vParam[0]); ofs << '\n'; } std::vector<double> vMax(reg.GetPF().GetDimensions()); if (reg.GetPF().GetMax(&vParam[0], &vMax[0])) { for (unsigned j = 0; j < vMax.size(); j++) ofsMax << std::setw(13) << vMax[j]; ofsMax << std::setw(13) << reg.GetPF().GetValue(&vParam[0], &vMax[0]); ofsMax << '\n'; } } } }
VOID CCharactor::Load( WCHAR* a_pFileName ) { // 바운드 박스 파일에서 읽기로 수정. D3DXVECTOR3 vMin( 99999.0f, 99999.0f, 99999.0f); D3DXVECTOR3 vMax(-99999.0f, -99999.0f, -99999.0f); m_pBoundBox = new CBoundBox(this); m_pBoundBox->Create(); m_pModel->SetCharType( m_pBoundBox ); FILE* pFile; pFile = _wfopen( a_pFileName, L"r" ); if( NULL == pFile ) { MessageBox(GHWND, L"File Load Error", a_pFileName, MB_OK); return; } fseek( pFile, 0L, SEEK_SET ); INT iTemp; WCHAR szTemp[255]; fwscanf( pFile, L"%d", &iTemp ); fwscanf( pFile, L"%s", szTemp ); //m_pOctTree->Build( iTemp ); FLOAT fSize = 0.5f * iTemp; FLOAT fBBSize[2][3]; fBBSize[0][0] = fBBSize[0][1] = fBBSize[0][2] = 0.0f; // MIN fBBSize[1][0] = fBBSize[1][1] = fBBSize[1][2] = 0.0f; // MAX // 버텍스, 인덱스 버퍼 생성 if( FAILED( m_pD3dDevice->CreateVertexBuffer( CCube::CUBEVERTEX::VertexNum * sizeof( CCube::CUBEVERTEX ), 0, CCube::CUBEVERTEX::FVF, D3DPOOL_MANAGED, &m_pTotalVB, NULL ) ) ) { MessageBox(GHWND, L"Vertex Buffer Failed", NULL, MB_OK); } if( FAILED( m_pD3dDevice->CreateIndexBuffer( CCube::CUBEINDEX::IndexNum * sizeof( CCube::CUBEINDEX ), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pTotalIB, NULL ) ) ) { MessageBox(GHWND, L"Index Buffer Failed", NULL, MB_OK); } //_CleanUpLoad(); _CreateBase( iTemp, szTemp ); fwscanf( pFile, L"%d", &m_pObject->iCubeCount ); INT iVectorCount=0; fwscanf( pFile, L"%d", &iVectorCount ); //벡터 할당 m_vectorCube.resize( iVectorCount ); fwscanf( pFile, L"%d", &iTemp ); for(INT Loop=0; Loop<EnumCharFrame::MAXFRAME; ++Loop) { fwscanf( pFile, L"%s", szTemp ); fwscanf( pFile, L"%d", &iTemp ); if( iTemp != -1 ) { for(INT xLoop=0; xLoop<m_iBoxSize; ++xLoop) { for(INT yLoop=0; yLoop<m_iBoxSize; ++yLoop) { for(INT zLoop=0; zLoop<m_iBoxSize; ++zLoop) { DWORD dwColor; BOOL bVisible; D3DXVECTOR3 vPos; INT iIndex; INT iVectorIndex; INT iType; INT iFriendVecIndex[6]; fwscanf( pFile, L"%d %d %d %lx %d %f %f %f %d %d %d %d %d %d", &iIndex, &iVectorIndex, &iType, &dwColor, &bVisible, &vPos.x, &vPos.y, &vPos.z, &iFriendVecIndex[0], &iFriendVecIndex[1], &iFriendVecIndex[2], &iFriendVecIndex[3], &iFriendVecIndex[4], &iFriendVecIndex[5] ); //vPos.x = xLoop; //vPos.y = yLoop; //vPos.z = zLoop; //if( iVectorIndex != -1 ) //m_pOctTree->SetChildIndex(vPos, iVectorIndex ); if( iVectorIndex != -1 ) { if( Loop == EnumCharFrame::BASE ) { //벡터에 생성된 새 큐브 주소 넣기 m_vectorCube[ iVectorIndex ] = new CCharCube; m_vectorCube[ iVectorIndex ]->Create( m_pD3dDevice, m_pTotalVB, m_pTotalIB, /*(iVectorIndex * CCube::CUBEVERTEX::VertexNum)*/0, 0 ); m_vectorCube[ iVectorIndex ]->InitTexture( dwColor ); } m_vectorCube[ iVectorIndex ]->Set_NumIndex( Loop, iIndex ); m_vectorCube[ iVectorIndex ]->Set_Type( Loop, iType ); m_vectorCube[ iVectorIndex ]->Set_Color( Loop, dwColor ); m_vectorCube[ iVectorIndex ]->Set_Visible( Loop, bVisible); m_vectorCube[ iVectorIndex ]->Set_Pos( Loop, vPos ); m_vectorCube[ iVectorIndex ]->Set_FriendCubeVecIndex( Loop, 0, iFriendVecIndex[0] ); m_vectorCube[ iVectorIndex ]->Set_FriendCubeVecIndex( Loop, 1, iFriendVecIndex[1] ); m_vectorCube[ iVectorIndex ]->Set_FriendCubeVecIndex( Loop, 2, iFriendVecIndex[2] ); m_vectorCube[ iVectorIndex ]->Set_FriendCubeVecIndex( Loop, 3, iFriendVecIndex[3] ); m_vectorCube[ iVectorIndex ]->Set_FriendCubeVecIndex( Loop, 4, iFriendVecIndex[4] ); m_vectorCube[ iVectorIndex ]->Set_FriendCubeVecIndex( Loop, 5, iFriendVecIndex[5] ); m_vectorCube[iVectorIndex]->Set_ControlTranslate( 0, m_vectorCube[iVectorIndex]->Get_Pos( Loop ).x ); m_vectorCube[iVectorIndex]->Set_ControlTranslate( 1, m_vectorCube[iVectorIndex]->Get_Pos( Loop ).y ); m_vectorCube[iVectorIndex]->Set_ControlTranslate( 2, m_vectorCube[iVectorIndex]->Get_Pos( Loop ).z ); m_vectorCube[iVectorIndex]->Calcul_MatWorld(); m_vectorCube[iVectorIndex]->Set_Matrix( Loop, m_vectorCube[iVectorIndex]->Get_MatWorld() ); // Set BoundBox Size if (fBBSize[0][0] > vPos.x) fBBSize[0][0] = vPos.x; if (fBBSize[0][1] > vPos.y) fBBSize[0][1] = vPos.y; if (fBBSize[0][2] > vPos.z) fBBSize[0][2] = vPos.z; if (fBBSize[1][0] < vPos.x) fBBSize[1][0] = vPos.x; if (fBBSize[1][1] < vPos.y) fBBSize[1][1] = vPos.y; if (fBBSize[1][2] < vPos.z) fBBSize[1][2] = vPos.z; } } } } } fwscanf( pFile, L"%s", szTemp ); } m_pBoundBox->SetSize(0, fBBSize[0][0]); m_pBoundBox->SetSize(1, fBBSize[0][1]); m_pBoundBox->SetSize(2, fBBSize[0][2]); m_pBoundBox->SetSize(3, fBBSize[1][0]); m_pBoundBox->SetSize(4, fBBSize[1][1]); m_pBoundBox->SetSize(5, fBBSize[1][2]); fclose( pFile ); m_iCubeVectorSize = static_cast<INT>( m_vectorCube.size() ); // 면단위 컬링시 사용 //for( INT Loop=0; Loop<m_iCubeVectorSize; ++Loop ) //{ // // 인터페이스에서 컬링이 온이라면 // if( m_vectorCube[Loop] != NULL && m_vectorCube[Loop]->Get_Visible( EnumCharFrame::BASE ) == TRUE ) // { // for(INT LoopCell=0; LoopCell<6; ++LoopCell) // { // if( -1 != m_vectorCube[Loop]->Get_FriendCubeVecIndex( m_iSelectedFrameNum, LoopCell ) ) // { // m_vectorCube[Loop]->Set_FaceVisible( LoopCell, FALSE ); // } // //else // //{ // // m_vectorCube[Loop]->Set_FaceVisible( LoopCell, TRUE ); // //} // } // } //} //MessageBox(GHWND, L"Load OK", a_pFileName, MB_OK); }
//given an animation and a keyframe, this will find the dims that encompass the //model bool CDimensionsDlg::FindAnimDims(Model* pModel, uint32 nAnim, uint32 nKeyFrame, LTVector& vDims) { //clear out the dims to start out with in case we fail vDims.Init(); AnimTracker tracker, *pTracker; tracker.m_TimeRef.Init(pModel, nAnim, nKeyFrame, nAnim, nKeyFrame, 0.0f); AnimInfo *pAnim = &pModel->m_Anims[nAnim]; pTracker = &tracker;//pAnim->m_pAnim; static CMoArray<TVert> tVerts; // Use the model code to setup the vertices. int nTrackers = 1; nTrackers = DMIN(nTrackers, MAX_GVP_ANIMS); GVPStruct gvp; gvp.m_nAnims = 0; for(int i = 0; i < nTrackers; i++) { gvp.m_Anims[i] = pTracker[i].m_TimeRef; gvp.m_nAnims++; } LTMatrix m; m.Identity(); int nWantedVerts = pModel->GetTotalNumVerts() * 2; if(tVerts.GetSize() < nWantedVerts) { if(!tVerts.SetSize(nWantedVerts)) return false; } gvp.m_VertexStride = sizeof(TVert); gvp.m_Vertices = tVerts.GetArray(); gvp.m_BaseTransform = m; gvp.m_CurrentLODDist = 0; if (AlternateGetVertexPositions(pModel, &gvp, true, false, false, false)) { LTVector vMax(0, 0, 0); for (i = 0; i < pModel->GetTotalNumVerts(); i ++) { TVert v = tVerts[i]; if (fabs(v.m_vPos.x) > vMax.x) vMax.x = (float)fabs(v.m_vPos.x); if (fabs(v.m_vPos.y) > vMax.y) vMax.y = (float)fabs(v.m_vPos.y); if (fabs(v.m_vPos.z) > vMax.z) vMax.z = (float)fabs(v.m_vPos.z); } // Setup the new dims.... //round max up to the .1 decimal place vMax.x = (float)(ceil(vMax.x * 10.0) / 10.0); vMax.y = (float)(ceil(vMax.y * 10.0) / 10.0); vMax.z = (float)(ceil(vMax.z * 10.0) / 10.0); vDims = vMax; return true; } //failure return false; }
/*------------------------------ doThreshAnalysis description: do the threshold analysis using the specified channel, and using the sample blocks as the "trigger" input: int chNum- the channel in the signal to use output: basicStats - the stats for this channel */ basicStats analysis::doThreshAnalysis(int chNum) { vector<double> tDiff; basicStats tmpStat; tmpStat.mean = -1; tmpStat.std = -1; tmpStat.min = -1; tmpStat.max = -1; if (chNum >= nChannels || chNum < 0) return tmpStat; //normalize the data by subtracting the minimum value, and dividing by the max //giving us values between 0 and 1 double sMin = getMin(signal[chNum], nSamples); double *sigTmp = new double[nSamples]; for (int i = 0; i < nSamples; i++) sigTmp[i] = signal[chNum][i] - sMin; //now normalize the data double sMax = getMax(sigTmp, nSamples); if (sMax == 0) return tmpStat; for (int i = 0; i < nSamples; i++) sigTmp[i] /= sMax; //get the time differences int sigPos = 0; for (int sample = blockSize; sample < nSamples-blockSize; sample += blockSize) { //record the starting sample sigPos = sample; //first check that the signal already is not above threshold, //and if it is, just continue if (sigTmp[sigPos] > thresh && sigTmp[sigPos-1] >= thresh) continue; //go through the signal, and increment the signal position until it //crosses the threshold while ((sigTmp[sigPos] < thresh) && ((sigPos-sample) < blockSize)) sigPos++; //the signal has crossed the threshold, so record the time difference //from the first sample in the block to when this occurred, //converted to ms, and add it to the tDiff vector if (sigPos >= sample) tDiff.push_back(((float)sigPos-(float)sample)/sampleRate*1000); } if (tDiff.size() == 0) return tmpStat; //find the mean, std, etc tmpStat.mean = vMean(&tDiff); tmpStat.std = vStd(&tDiff); tmpStat.min = vMin(&tDiff); tmpStat.max = vMax(&tDiff); tmpStat.vals = tDiff; stringstream str; str << "Ch " << chNum <<" v. blocks"; tmpStat.desc = str.str(); return tmpStat; }
double pivot(double * v, size_t len, double target) { // Rprintf("Entering pivot with len=%d and target=%f\n ", len, target); // RprintV(v, len); if (len > 2) { // pick the pivot, say as the median of the first, middle and last size_t i1 = 0, i2 = len-1, i3 = (len-1)/2, ip; if (v[i1] <= v[i2]) { if (v[i2] <= v[i3]) ip = i2; else if (v[i3] >= v[i1]) ip = i3; else ip = i1; } else { if (v[i1] <= v[i3]) ip = i1; else if (v[i2] <= v[i3]) ip = i3; else ip = i2; } // put ip at the end double vp = v[ip]; v[ip] = v[len-1]; v[len-1] = vp; // Rprintf(" pivot value: %5.3f, index: %d\n", vp, ip); // pivot everything else size_t bound = 0; for (size_t i=0; i<len; i++) if (v[i] < vp) { double x = v[bound]; v[bound] = v[i]; v[i] = x; bound++; } v[len-1] = v[bound]; v[bound] = vp; // Rprintf(" After pivoting: bound:%d and vector: ", bound); // RprintV(v, len); // Did we find the target? double crit = target - bound; // Rprintf(" crit: %5.3f\n", crit); if (fabs(crit) > 1.0) { if (crit < 0) return pivot(v, bound, target); else return pivot(v+bound+1, len-bound-1, target-bound-1); } // Rprintf("vMax(v, bound): %5.3f, vMin(v+bound+1, len-bound-1): %5.3f, vp: %5.3f\n", vMax(v, bound), // vMin(v+bound+1, len-bound-1), vp); if (crit < 0) { double v1 = vMax(v, bound); return (v1 *(-crit) + vp * (1+crit)); } // else double v2 = vMin(v+bound+1, len-bound-1); return (vp * (1-crit) + v2 * crit); } else if (len==2) { // Rprintf(" Short v, returning a direct value.\n"); double v1 = vMin(v, 2); double v2 = vMax(v, 2); if (target < 0) return v1; else if (target > 1) return v2; else return (target * v2 + (1-target) * v1); } else { // Rprintf(" length 1 v, returning a direct value.\n"); return v[0]; } }
/** * CParticleEffect::initParticle * @date Modified June 01, 2006 */ void CParticleEffect::initParticle(CParticleManager::SParticle* pParticle, D3DXMATRIX* mOffset) { D3DXMATRIX mPosOffset, mOrientation = *mOffset; D3DXMatrixIdentity(&mPosOffset); mPosOffset._41 = mOffset->_41; mPosOffset._42 = mOffset->_42; mPosOffset._43 = mOffset->_43; mOrientation._41 = mOrientation._42 = mOrientation._43 = 0.0f; mOrientation._44 = 1.0f; float fMinVel, fMaxVel; D3DXVec3Normalize(&fMinVel, &m_vMinVelocity, &m_vMinVelocity); D3DXVec3Normalize(&fMaxVel, &m_vMaxVelocity, &m_vMaxVelocity); D3DXVec3TransformCoord(&m_vMinVelocityTrans, &m_vMinVelocity, &mOrientation); D3DXVec3TransformCoord(&m_vMaxVelocityTrans, &m_vMaxVelocity, &mOrientation); m_vMinVelocity *= fMinVel; m_vMaxVelocity *= fMaxVel; // Update attributes BYTE cR = GET_RED(pParticle->Color), cG = GET_GREEN(pParticle->Color), cB = GET_BLUE(pParticle->Color), cA = GET_ALPHA(pParticle->Color); for(size_t j = 0; j < m_vAttributes.size(); ++j) { float fScale = m_vAttributes[j]->getValue(0.0f); switch(m_vAttributes[j]->getType()) { case CParticleAttribute::ATR_COLORRED: cR = (BYTE)(fScale * 255.0f); break; case CParticleAttribute::ATR_COLORGREEN: cG = (BYTE)(fScale * 255.0f); break; case CParticleAttribute::ATR_COLORBLUE: cB = (BYTE)(fScale * 255.0f); break; case CParticleAttribute::ATR_COLORALPHA: cA = (BYTE)(fScale * 255.0f); break; case CParticleAttribute::ATR_SIZE: pParticle->Size = fScale; break; case CParticleAttribute::ATR_ROTATION: pParticle->Rotation = degreesToRadians(fScale); break; case CParticleAttribute::ATR_ACCELX: pParticle->Acceleration.x = fScale; break; case CParticleAttribute::ATR_ACCELY: pParticle->Acceleration.y = fScale; break; case CParticleAttribute::ATR_ACCELZ: pParticle->Acceleration.z = fScale; break; } } pParticle->Color = D3DCOLOR_ARGB(cA, cR, cG, cB); getRandomVector(&pParticle->Velocity, &m_vMinVelocityTrans, &m_vMaxVelocityTrans); pParticle->Velocity *= getRandomFloat(fMinVel, fMaxVel); m_vMinVelocityTrans *= fMinVel; m_vMaxVelocityTrans *= fMaxVel; D3DXVECTOR3 vMin(0.0f, 0.0f, 0.0f), vMax(0.0f, 0.0f, 0.0f); switch(m_eSpawnShape) { case SH_CUBE: vMin.x = -m_vSpawnRadius.x; vMin.y = -m_vSpawnRadius.y; vMin.z = -m_vSpawnRadius.z; getRandomVector(&pParticle->Position, &vMin, &m_vSpawnRadius); break; case SH_SQUARE: vMin.x = -m_vSpawnRadius.x; vMin.z = -m_vSpawnRadius.z; vMax.x = m_vSpawnRadius.x; vMax.z = m_vSpawnRadius.z; getRandomVector(&pParticle->Position, &vMin, &vMax); break; case SH_SPHERE: getRandomVector(&vMin, -1.0f, 1.0f); D3DXVec3Normalize(&vMin, &vMin); pParticle->Position.x = vMin.x * m_vSpawnRadius.x; pParticle->Position.y = vMin.y * m_vSpawnRadius.x; pParticle->Position.z = vMin.z * m_vSpawnRadius.x; break; case SH_CIRCLE: getRandomVector(&vMin, -1.0f, 1.0f); D3DXVec3Normalize(&vMin, &vMin); pParticle->Position.x = vMin.x * m_vSpawnRadius.x; pParticle->Position.y = 0.0f; pParticle->Position.z = vMin.z * m_vSpawnRadius.x; break; } D3DXVec3TransformCoord(&pParticle->Position, &pParticle->Position, &mPosOffset); }
/* * Prepare for projecting. */ void CPerspectiveProjection3D::Prepare(void) { FLOATmatrix3D t3dObjectStretch; // matrix for object stretch FLOATmatrix3D t3dObjectRotation; // matrix for object angles // calc. matrices for viewer and object angles and stretch MakeRotationMatrixFast( t3dObjectRotation, pr_ObjectPlacement.pl_OrientationAngle); MakeInverseRotationMatrixFast( pr_ViewerRotationMatrix, pr_ViewerPlacement.pl_OrientationAngle); t3dObjectStretch.Diagonal(pr_ObjectStretch); pr_vViewerPosition = pr_ViewerPlacement.pl_PositionVector; BOOL bXInverted = pr_ObjectStretch(1)<0; BOOL bYInverted = pr_ObjectStretch(2)<0; BOOL bZInverted = pr_ObjectStretch(3)<0; pr_bInverted = (bXInverted != bYInverted) != bZInverted; // if the projection is mirrored if (pr_bMirror) { // reflect viewer ReflectPositionVectorByPlane(pr_plMirror, pr_vViewerPosition); ReflectRotationMatrixByPlane_rows(pr_plMirror, pr_ViewerRotationMatrix); // get mirror plane in view space pr_plMirrorView = pr_plMirror; pr_plMirrorView -= pr_vViewerPosition; pr_plMirrorView *= pr_ViewerRotationMatrix; // invert inversion pr_bInverted = !pr_bInverted; } else if (pr_bWarp) { // get mirror plane in view space pr_plMirrorView = pr_plMirror; } // if the object is face-forward if (pr_bFaceForward) { // if it turns only heading if (pr_bHalfFaceForward) { // get the y-axis vector of object rotation FLOAT3D vY(t3dObjectRotation(1,2), t3dObjectRotation(2,2), t3dObjectRotation(3,2)); // find z axis of viewer FLOAT3D vViewerZ( pr_ViewerRotationMatrix(3,1), pr_ViewerRotationMatrix(3,2), pr_ViewerRotationMatrix(3,3)); // calculate x and z axis vectors to make object head towards viewer FLOAT3D vX = (-vViewerZ)*vY; vX.Normalize(); FLOAT3D vZ = vY*vX; // compose the rotation matrix back from those angles t3dObjectRotation(1,1) = vX(1); t3dObjectRotation(1,2) = vY(1); t3dObjectRotation(1,3) = vZ(1); t3dObjectRotation(2,1) = vX(2); t3dObjectRotation(2,2) = vY(2); t3dObjectRotation(2,3) = vZ(2); t3dObjectRotation(3,1) = vX(3); t3dObjectRotation(3,2) = vY(3); t3dObjectRotation(3,3) = vZ(3); // first apply object stretch then object rotation and then viewer rotation pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; // if it is fully face forward } else { // apply object stretch and banking only FLOATmatrix3D mBanking; MakeRotationMatrixFast( mBanking, ANGLE3D(0,0, pr_ObjectPlacement.pl_OrientationAngle(3))); pr_mDirectionRotation = mBanking; pr_RotationMatrix = mBanking*t3dObjectStretch; } } else { // first apply object stretch then object rotation and then viewer rotation pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; } // calc. offset of object from viewer pr_TranslationVector = pr_ObjectPlacement.pl_PositionVector - pr_vViewerPosition; // rotate offset only by viewer angles pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix; // transform handle from object space to viewer space and add it to the offset pr_TranslationVector -= pr_vObjectHandle*pr_RotationMatrix; FLOAT2D vMin, vMax; // if using a shadow projection if (ppr_fMetersPerPixel>0) { // caclulate factors FLOAT fFactor = ppr_fViewerDistance/ppr_fMetersPerPixel; ppr_PerspectiveRatios(1) = -fFactor; ppr_PerspectiveRatios(2) = -fFactor; pr_ScreenCenter = -pr_ScreenBBox.Min(); vMin = pr_ScreenBBox.Min(); vMax = pr_ScreenBBox.Max(); // if using normal projection } else if (ppr_boxSubScreen.IsEmpty()) { // calculate perspective constants FLOAT2D v2dScreenSize = pr_ScreenBBox.Size(); pr_ScreenCenter = pr_ScreenBBox.Center(); /* calculate FOVHeight from FOVWidth by formula: halfanglej = atan( tan(halfanglei)*jsize*aspect/isize ) */ ANGLE aHalfI = ppr_FOVWidth/2; ANGLE aHalfJ = ATan(TanFast(aHalfI)*v2dScreenSize(2)*pr_AspectRatio/v2dScreenSize(1)); /* calc. perspective ratios by formulae: xratio = isize/(2*tan(anglei/2)) yratio = jsize/(2*tan(anglej/2)) sign is negative since viewer is looking down the -z axis */ ppr_PerspectiveRatios(1) = -v2dScreenSize(1)/(2.0f*TanFast(aHalfI))*pr_fViewStretch; ppr_PerspectiveRatios(2) = -v2dScreenSize(2)/(2.0f*TanFast(aHalfJ))*pr_fViewStretch; vMin = pr_ScreenBBox.Min()-pr_ScreenCenter; vMax = pr_ScreenBBox.Max()-pr_ScreenCenter; // if using sub-drawport projection } else { // calculate perspective constants FLOAT2D v2dScreenSize = pr_ScreenBBox.Size(); pr_ScreenCenter = pr_ScreenBBox.Center(); /* calculate FOVHeight from FOVWidth by formula: halfanglej = atan( tan(halfanglei)*jsize*aspect/isize ) */ ANGLE aHalfI = ppr_FOVWidth/2; ANGLE aHalfJ = ATan(TanFast(aHalfI)*v2dScreenSize(2)*pr_AspectRatio/v2dScreenSize(1)); /* calc. perspective ratios by formulae: xratio = isize/(2*tan(anglei/2)) yratio = jsize/(2*tan(anglej/2)) sign is negative since viewer is looking down the -z axis */ ppr_PerspectiveRatios(1) = -v2dScreenSize(1)/(2.0f*TanFast(aHalfI))*pr_fViewStretch; ppr_PerspectiveRatios(2) = -v2dScreenSize(2)/(2.0f*TanFast(aHalfJ))*pr_fViewStretch; vMin = ppr_boxSubScreen.Min()-pr_ScreenCenter; vMax = ppr_boxSubScreen.Max()-pr_ScreenCenter; pr_ScreenCenter -= ppr_boxSubScreen.Min(); } // find factors for left, right, up and down clipping FLOAT fMinI = vMin(1); FLOAT fMinJ = vMin(2); FLOAT fMaxI = vMax(1); FLOAT fMaxJ = vMax(2); FLOAT fRatioX = ppr_PerspectiveRatios(1); FLOAT fRatioY = ppr_PerspectiveRatios(2); #define MySgn(x) ((x)>=0?1:-1) FLOAT fDZ = -1.0f; FLOAT fDXL = fDZ*fMinI/fRatioX; FLOAT fDXR = fDZ*fMaxI/fRatioX; FLOAT fDYU = -fDZ*fMinJ/fRatioY; FLOAT fDYD = -fDZ*fMaxJ/fRatioY; FLOAT fNLX = -fDZ; FLOAT fNLZ = +fDXL; FLOAT fOoNL = 1.0f/(FLOAT)sqrt(fNLX*fNLX+fNLZ*fNLZ); fNLX*=fOoNL; fNLZ*=fOoNL; FLOAT fNRX = +fDZ; FLOAT fNRZ = -fDXR; FLOAT fOoNR = 1.0f/(FLOAT)sqrt(fNRX*fNRX+fNRZ*fNRZ); fNRX*=fOoNR; fNRZ*=fOoNR; FLOAT fNDY = -fDZ; FLOAT fNDZ = +fDYD; FLOAT fOoND = 1.0f/(FLOAT)sqrt(fNDY*fNDY+fNDZ*fNDZ); fNDY*=fOoND; fNDZ*=fOoND; FLOAT fNUY = +fDZ; FLOAT fNUZ = -fDYU; FLOAT fOoNU = 1.0f/(FLOAT)sqrt(fNUY*fNUY+fNUZ*fNUZ); fNUY*=fOoNU; fNUZ*=fOoNU; // make clip planes pr_plClipU = FLOATplane3D(FLOAT3D( 0,fNUY,fNUZ), 0.0f); pr_plClipD = FLOATplane3D(FLOAT3D( 0,fNDY,fNDZ), 0.0f); pr_plClipL = FLOATplane3D(FLOAT3D(fNLX, 0,fNLZ), 0.0f); pr_plClipR = FLOATplane3D(FLOAT3D(fNRX, 0,fNRZ), 0.0f); // mark as prepared pr_Prepared = TRUE; // calculate constant value used for calculating z-buffer k-value from vertex's z coordinate pr_fDepthBufferFactor = -pr_NearClipDistance; pr_fDepthBufferMul = pr_fDepthBufferFar-pr_fDepthBufferNear; pr_fDepthBufferAdd = pr_fDepthBufferNear; // calculate ratio for mip factor calculation ppr_fMipRatio = pr_ScreenBBox.Size()(1)/(ppr_PerspectiveRatios(1)*640.0f); }
/** * Parses a navPoly / waypoint section * * @param pSection the DataSection to parse. * @param pChunk if not NULL this flags that we are parsing a navPoly not a * waypoint section as well as providing the chunk from which to get the * transform information to go from local -> global coords. */ void ChunkView::parseNavPoly( DataSectionPtr pSection, int set, Chunk * pChunk ) { DataSection::iterator it; PolygonDef polyDef; int id; float height; id = pSection->asInt(); height = pSection->readFloat("height"); polyDef.minHeight = pSection->readFloat("minHeight",height); polyDef.maxHeight = pSection->readFloat("maxHeight",height); polyDef.set = set; // If chunk provided, we want to convert heights from local -> global coords. if (pChunk) { Vector3 vMin( pChunk->centre().x, polyDef.minHeight, pChunk->centre().z ); Vector3 vMax( pChunk->centre().x, polyDef.maxHeight, pChunk->centre().z ); Vector3 vMinT = pChunk->transform().applyPoint( vMin ); Vector3 vMaxT = pChunk->transform().applyPoint( vMax ); polyDef.minHeight = vMinT.y; polyDef.maxHeight = vMaxT.y; } // If there is a gap in IDs, add blank polys to fill it up. while (nextID_ <= id) { PolygonDef blankPoly; blankPoly.minHeight = 0.0f; blankPoly.maxHeight = 0.0f; blankPoly.set = 0; polygons_.push_back(blankPoly); nextID_++; } // Read all this navPoly's vertices for(it = pSection->begin(); it != pSection->end(); it++) { if((*it)->sectionName() == "vertex") { DataSectionPtr pVertex = *it; VertexDef vertexDef; Vector3 vinfo = pVertex->asVector3(); vertexDef.position.x = vinfo.x; vertexDef.position.y = vinfo.y; vertexDef.adjacentID = int( vinfo.z ); // if pChunk provided, want to convert vertex to golbal coords. if (pChunk) { Vector3 v( vinfo.x, polyDef.maxHeight, vinfo.y ); Vector3 vT = pChunk->transform().applyPoint( v ); vertexDef.position.x = vT.x; vertexDef.position.y = vT.z; } std::string notFound( "__NOT_FOUND__" ); std::string adjacentChunk = pVertex->readString("adjacentChunk",notFound); // if there is an adjacentChunk tag // note: only ever occurs within legacy waypoint tags. if ( adjacentChunk != notFound ) { if (vertexDef.adjacentID != 0) { WARNING_MSG( "ChunkView::parseNavPoly: adjacentChunk tag" " found but edge adjacency not 0.\n" ); } vertexDef.adjacentID = CHUNK_ADJACENT_CONSTANT; } // if adjacent to another chunk, flag this in vertexDef. // also make (navPoly) adjacentID more sensible. vertexDef.adjToAnotherChunk = false; if (vertexDef.adjacentID == CHUNK_ADJACENT_CONSTANT) { vertexDef.adjacentID = 0; vertexDef.adjToAnotherChunk = true; } polyDef.vertices.push_back( vertexDef ); if(!minMaxValid_) { gridMin_.x = vertexDef.position.x; gridMin_.z = vertexDef.position.y; gridMin_.y = -1000.0f; gridMax_.x = vertexDef.position.x; gridMax_.z = vertexDef.position.y; gridMax_.y = 1000.0f; minMaxValid_ = true; } else { if(vertexDef.position.x < gridMin_.x) gridMin_.x = vertexDef.position.x; if(vertexDef.position.y < gridMin_.z) gridMin_.z = vertexDef.position.y; if(vertexDef.position.x > gridMax_.x) gridMax_.x = vertexDef.position.x; if(vertexDef.position.y > gridMax_.z) gridMax_.z = vertexDef.position.y; } } } polygons_[id-1] = polyDef; }
// Calculate the quantization factors void CIFXPointSetEncoder::CalculateQuantizationFactorsX() { U32 uQualityFactor = 1000; m_pPointSetResource->GetQualityFactorX(uQualityFactor,IFXAuthorPointSetResource::POSITION_QUALITY); if(1000 == uQualityFactor) { m_fQuantPosition = (F32) pow(2.0,18.0); } else { m_fQuantPosition = (F32) pow(1.0076537604105041221998506395494,uQualityFactor+545.0); } // Scale m_fQuantPosition by the radius of the bounding sphere IFXASSERT(m_pAuthorPointSet); // get the Point set description const IFXAuthorPointSetDesc* pPointSetDescription = m_pAuthorPointSet->GetMaxPointSetDesc(); IFXASSERT(pPointSetDescription); IFXASSERT(pPointSetDescription->m_numPositions > 0); IFXVector3* pPosition = NULL; IFXCHECKX(m_pAuthorPointSet->GetPositions(&pPosition)); // Calculate the center of the bounding sphere IFXVector3 vMin(pPosition[0]), vMax(pPosition[0]); U32 i = 0; U32 uNumPositions = pPointSetDescription->m_numPositions; for(i = 1; i < uNumPositions ; i++) { vMin.X() += (pPosition[i].X() - vMin.X()) * (pPosition[i].X() < vMin.X()); vMin.Y() += (pPosition[i].Y() - vMin.Y()) * (pPosition[i].Y() < vMin.Y()); vMin.Z() += (pPosition[i].Z() - vMin.Z()) * (pPosition[i].Z() < vMin.Z()); vMax.X() += (pPosition[i].X() - vMax.X()) * (pPosition[i].X() > vMax.X()); vMax.Y() += (pPosition[i].Y() - vMax.Y()) * (pPosition[i].Y() > vMax.Y()); vMax.Z() += (pPosition[i].Z() - vMax.Z()) * (pPosition[i].Z() > vMax.Z()); } IFXVector3 vCenter(vMin); vCenter.Add(vMax); vCenter.Scale(0.5f); // Calculate the radius of the bounding sphere F32 fRadiusSquared = 0.0f; F32 fDistanceSquared = 0.0f; for(i=0; i < uNumPositions; i++) { fDistanceSquared = vCenter.CalcDistanceSquaredFrom(pPosition[i]); fRadiusSquared += (fDistanceSquared - fRadiusSquared) * (fDistanceSquared > fRadiusSquared); } // Scale the position quantization factor by the radius of the bounding sphere if(fRadiusSquared > 0.0f) { m_fQuantPosition /= sqrtf(fRadiusSquared); } // Limit quantization factor to fit quantized results in 32 bit unsigned integer { // Find position coordinate farthest from the origin F32 fMaxPositionCoordinate; fMaxPositionCoordinate = IFXMAX(fabs(vMax.X()),fabs(vMax.Y())); fMaxPositionCoordinate = IFXMAX(fMaxPositionCoordinate,fabs(vMax.Z())); fMaxPositionCoordinate = IFXMAX(fMaxPositionCoordinate,fabs(vMin.X())); fMaxPositionCoordinate = IFXMAX(fMaxPositionCoordinate,fabs(vMin.Y())); fMaxPositionCoordinate = IFXMAX(fMaxPositionCoordinate,fabs(vMin.Z())); F32 fLimit = (F32) (0xFFFFFE00); // (F32) (0xFFFFFE00) F32 fMaxQuantPosition = fLimit / fMaxPositionCoordinate; // Clamp position quantization factor m_fQuantPosition = IFXMIN(m_fQuantPosition,fMaxQuantPosition); } m_pPointSetResource->GetQualityFactorX(uQualityFactor,IFXAuthorPointSetResource::NORMAL_QUALITY); if(1000 == uQualityFactor) { m_fQuantNormal = (F32) pow(2.0,14.0); } else { m_fQuantNormal = (F32) pow(1.0048638204237854409678879459798,uQualityFactor+857.0); } m_pPointSetResource->GetQualityFactorX(uQualityFactor,IFXAuthorPointSetResource::TEXCOORD_QUALITY); if(1000 == uQualityFactor) { m_fQuantTexCoord = (F32) pow(2.0,14.0); } else { m_fQuantTexCoord = (F32) pow(1.0048638204237854409678879459798,uQualityFactor+857.0); } m_pPointSetResource->GetQualityFactorX(uQualityFactor,IFXAuthorPointSetResource::DIFFUSE_QUALITY); if(1000 == uQualityFactor) { m_fQuantDiffuseColor = (F32) pow(2.0,14.0); } else { m_fQuantDiffuseColor = (F32) pow(1.0022294514890519310704865897552,uQualityFactor+1741.0); } m_pPointSetResource->GetQualityFactorX(uQualityFactor,IFXAuthorPointSetResource::SPECULAR_QUALITY); if(1000 == uQualityFactor) { m_fQuantSpecularColor = (F32) pow(2.0,14.0); } else { m_fQuantSpecularColor = (F32) pow(1.0022294514890519310704865897552,uQualityFactor+1741.0); } m_fInverseQuantPosition = (F32) 1.0 / m_fQuantPosition; m_fInverseQuantNormal = (F32) 1.0 / m_fQuantNormal; m_fInverseQuantTexCoord = (F32) 1.0 / m_fQuantTexCoord; m_fInverseQuantDiffuseColor = (F32) 1.0 /m_fQuantDiffuseColor; m_fInverseQuantSpecularColor = (F32) 1.0 /m_fQuantSpecularColor; }
/*------------------------------ doThreshAnalysis description: this version of the analysis uses a specified recorded channel, and triggers off of a state when that state changes to a given value input: int chNum - the channel to use in the analysis string stateName - the state name to use for triggering int stateVal - the value that the state must change to to trigger (0 triggers ANY positive state change) output: basicStats - the results of the analysis */ basicStats analysis::doThreshAnalysis(int chNum, string stateName, int stateVal) { vector<double> tDiff; basicStats tmpStat; tmpStat.mean = -1; tmpStat.std = -1; tmpStat.min = -1; tmpStat.max = -1; //normalize the data by subtracting the minimum value, and dividing by the max //giving us values between 0 and 1 if (chNum >= nChannels || chNum < 0) return tmpStat; map<string, double*>::iterator itr = states.find(stateName); if (itr == states.end()) return tmpStat; double sMin = getMin(signal[chNum], nSamples); double *sigTmp = new double[nSamples]; for (int i = 0; i < nSamples; i++) sigTmp[i] = signal[chNum][i] - sMin; //now normalize the data double sMax = getMax(sigTmp, nSamples); if (sMax == 0) return tmpStat; for (int i = 0; i < nSamples; i++) sigTmp[i] /= sMax; //get the time differences //this finds both EACH state transition and COMBINED state transitions map<int, vector<double> > stateTDiffs; int sigPos = 0; int dState; for (int sample = 1; sample < nSamples-blockSize; sample += 1) { //get the transition value dState = (states[stateName][sample]-states[stateName][sample-1]); //we are only looking for positive CHANGES in the state if (dState <= 0) continue; sigPos = sample; //first check that the signal already is not above threshold, //and if it is, just continue if (sigTmp[sigPos] > thresh && sigTmp[sigPos-1] > thresh) continue; //look for the sample in the signal where it crosses the threshold while (sigTmp[sigPos] < thresh && sigPos < nSamples) sigPos++; //calculate the time difference float D = ((float)sigPos-(float)sample)/sampleRate*1000; if (sigPos > sample && sigPos < nSamples) { //store the time difference if the state change value is 0 or equal to what we specified if (stateVal == 0 || (stateVal == dState)) tDiff.push_back(D); else if (stateVal == -1) { //if we set state val to -1, we record all differences, and keep track of //the times for each dState value tDiff.push_back(D); stateTDiffs[dState].push_back(D); } } } if (tDiff.size() == 0) return tmpStat; //calculate the stats on the tDiff vector tmpStat.mean = vMean(&tDiff); tmpStat.std = vStd(&tDiff); tmpStat.min = vMin(&tDiff); tmpStat.max = vMax(&tDiff); //tmpStat.vals = tDiff; stringstream str; str << "Ch " << chNum <<" v. " << stateName; if (stateVal > 0) str <<"("<<stateVal<<")"; tmpStat.desc = str.str(); if (stateVal >= 0) return tmpStat; //now compare all of the states if stateVal == -1 //we keep the state with the smallest overall mean and return its map<int, vector<double> >::iterator it; it = stateTDiffs.begin(); double minMean = tmpStat.mean; for (it = stateTDiffs.begin(); it != stateTDiffs.end(); it++) { double tmpMean = vMean(&it->second); if (tmpMean < minMean) { minMean = tmpMean; tmpStat.mean = vMean(&it->second); tmpStat.std = vStd(&it->second); tmpStat.min = vMin(&it->second); tmpStat.max = vMax(&it->second); tmpStat.vals = it->second; stringstream str; str << "Ch " << chNum <<" v. " << stateName << "("<<it->first<<")"; tmpStat.desc = str.str(); } } return tmpStat; }
bool ModelImport::ImportObj(const std::string& srcFilename, std::string& dstFilename) { const AssetLib::AssetDef& rAssetDef = AssetLib::Model::GetAssetDef(); std::ifstream srcFile(srcFilename); assert(srcFile.is_open()); std::ofstream dstFile(dstFilename, std::ios::binary); assert(dstFile.is_open()); // Write header AssetLib::BinFileHeader header; header.binUID = AssetLib::BinFileHeader::kUID; header.assetUID = rAssetDef.GetAssetUID(); header.version = rAssetDef.GetBinVersion(); header.srcHash = Hashing::SHA1(); dstFile.write((char*)&header, sizeof(header)); // Build and write the main geo data GeoData geo; ObjData obj; char line[1024]; int lineNum = 0; // for debugging while (srcFile.getline(line, 1024)) { ++lineNum; char* context = nullptr; char* tok = strtok_s(line, " ", &context); if (strcmp(tok, "v") == 0) { // Position Vec3 pos; pos.x = (float)atof(strtok_s(nullptr, " ", &context)); pos.y = (float)atof(strtok_s(nullptr, " ", &context)); pos.z = (float)atof(strtok_s(nullptr, " ", &context)); obj.positions.push_back(pos); } else if (strcmp(tok, "vn") == 0) { // Normal Vec3 norm; norm.x = (float)atof(strtok_s(nullptr, " ", &context)); norm.y = (float)atof(strtok_s(nullptr, " ", &context)); norm.z = (float)atof(strtok_s(nullptr, " ", &context)); obj.normals.push_back(norm); } else if (strcmp(tok, "vt") == 0) { // Tex coord Vec2 uv; uv.x = (float)atof(strtok_s(nullptr, " ", &context)); uv.y = (float)atof(strtok_s(nullptr, " ", &context)); obj.texcoords.push_back(uv); } else if (strcmp(tok, "f") == 0) { // Face for (int i = 0; i < 3; ++i) { ObjVertex objVert; objVert.iPos = atoi(strtok_s(nullptr, "/ ", &context)) - 1; objVert.iUv = atoi(strtok_s(nullptr, "/ ", &context)) - 1; objVert.iNorm = atoi(strtok_s(nullptr, "/ ", &context)) - 1; // Find matching vert to re-use. int reuseIndex = -1; for (int v = (int)obj.verts.size() - 1; v >= 0; --v) { const ObjVertex& otherVert = obj.verts[v]; if (otherVert.iPos == objVert.iPos && otherVert.iUv == objVert.iUv && otherVert.iNorm == objVert.iNorm) { reuseIndex = v; break; } } if (reuseIndex >= 0) { geo.indices.push_back((uint16)reuseIndex); } else { geo.indices.push_back((uint16)geo.positions.size()); Color color = { 1.f, 1.f, 1.f, 1.f }; geo.positions.push_back(obj.positions[objVert.iPos]); geo.texcoords.push_back(obj.texcoords[objVert.iUv]); geo.normals.push_back(obj.normals[objVert.iNorm]); geo.colors.push_back(color); obj.verts.push_back(objVert); } } } else if (strcmp(tok, "usemtl") == 0) { std::string material = strtok_s(nullptr, " ", &context); obj.materials.push_back(material); obj.subobjectStartIndices.push_back((uint)geo.indices.size()); } } obj.subobjectStartIndices.push_back((uint)geo.indices.size()); geo.tangents.resize(geo.positions.size()); geo.bitangents.resize(geo.positions.size()); // TODO: Tangents/bitangents for shared verts for (uint i = 0; i < geo.indices.size(); i += 3) { uint v0 = geo.indices[i + 0]; uint v1 = geo.indices[i + 1]; uint v2 = geo.indices[i + 2]; const Vec3& pos0 = geo.positions[v0]; const Vec3& pos1 = geo.positions[v1]; const Vec3& pos2 = geo.positions[v2]; const Vec2& uv0 = geo.texcoords[v0]; const Vec2& uv1 = geo.texcoords[v1]; const Vec2& uv2 = geo.texcoords[v2]; Vec3 edge1 = pos1 - pos0; Vec3 edge2 = pos2 - pos0; Vec2 uvEdge1 = uv1 - uv0; Vec2 uvEdge2 = uv2 - uv0; float r = 1.f / (uvEdge1.y * uvEdge2.x - uvEdge1.x * uvEdge2.y); Vec3 tangent = (edge1 * -uvEdge2.y + edge2 * uvEdge1.y) * r; Vec3 bitangent = (edge1 * -uvEdge2.x + edge2 * uvEdge1.x) * r; tangent = Vec3Normalize(tangent); bitangent = Vec3Normalize(bitangent); geo.tangents[v0] = geo.tangents[v1] = geo.tangents[v2] = tangent; geo.bitangents[v0] = geo.bitangents[v1] = geo.bitangents[v2] = bitangent; } // Calc radius Vec3 vMin(FLT_MAX, FLT_MAX, FLT_MAX); Vec3 vMax(-FLT_MIN, -FLT_MIN, -FLT_MIN); for (int i = (int)geo.positions.size() - 1; i >= 0; --i) { vMin.x = std::min(geo.positions[i].x, vMin.x); vMax.x = std::max(geo.positions[i].x, vMax.x); vMin.y = std::min(geo.positions[i].y, vMin.y); vMax.y = std::max(geo.positions[i].y, vMax.y); vMin.z = std::min(geo.positions[i].z, vMin.z); vMax.z = std::max(geo.positions[i].z, vMax.z); } Vec3 modelBoundsMin(FLT_MAX, FLT_MAX, FLT_MAX); Vec3 modelBoundsMax(-FLT_MIN, -FLT_MIN, -FLT_MIN); uint totalVertCount = 0; for (int i = 0; i < obj.subobjectStartIndices.size() - 1; ++i) { AssetLib::Model::SubObject subobj; strcpy_s(subobj.materialName, obj.materials[i].c_str()); subobj.indexCount = obj.subobjectStartIndices[i + 1] - obj.subobjectStartIndices[i]; uint16 vertMin = -1; uint16 vertMax = 0; subobj.boundsMin = Vec3(FLT_MAX, FLT_MAX, FLT_MAX); subobj.boundsMax = Vec3(-FLT_MIN, -FLT_MIN, -FLT_MIN); for (uint tri = obj.subobjectStartIndices[i]; tri < obj.subobjectStartIndices[i + 1]; ++tri) { uint16 iVert = geo.indices[tri]; vertMin = std::min(iVert, vertMin); vertMax = std::max(iVert, vertMax); subobj.boundsMin.x = std::min(geo.positions[iVert].x, subobj.boundsMin.x); subobj.boundsMax.x = std::max(geo.positions[iVert].x, subobj.boundsMax.x); subobj.boundsMin.y = std::min(geo.positions[iVert].y, subobj.boundsMin.y); subobj.boundsMax.y = std::max(geo.positions[iVert].y, subobj.boundsMax.y); subobj.boundsMin.z = std::min(geo.positions[iVert].z, subobj.boundsMin.z); subobj.boundsMax.z = std::max(geo.positions[iVert].z, subobj.boundsMax.z); } subobj.vertCount = (vertMax - vertMin) + 1; totalVertCount += subobj.vertCount; modelBoundsMin = Vec3Min(modelBoundsMin, subobj.boundsMin); modelBoundsMax = Vec3Max(modelBoundsMax, subobj.boundsMax); geo.subobjects.push_back(subobj); } assert(totalVertCount == (uint)geo.positions.size()); AssetLib::Model modelBin; modelBin.totalVertCount = totalVertCount; modelBin.totalIndexCount = (uint)geo.indices.size(); modelBin.boundsMin = modelBoundsMin; modelBin.boundsMax = modelBoundsMax; modelBin.subObjectCount = (uint)geo.subobjects.size(); modelBin.subobjects.offset = 0; modelBin.positions.offset = modelBin.subobjects.offset + modelBin.subobjects.CalcSize(modelBin.subObjectCount); modelBin.texcoords.offset = modelBin.positions.offset + modelBin.positions.CalcSize(totalVertCount); modelBin.normals.offset = modelBin.texcoords.offset + modelBin.texcoords.CalcSize(totalVertCount); modelBin.colors.offset = modelBin.normals.offset + modelBin.normals.CalcSize(totalVertCount); modelBin.tangents.offset = modelBin.colors.offset + modelBin.colors.CalcSize(totalVertCount); modelBin.bitangents.offset = modelBin.tangents.offset + modelBin.tangents.CalcSize(totalVertCount); modelBin.indices.offset = modelBin.bitangents.offset + modelBin.bitangents.CalcSize(totalVertCount); dstFile.write((char*)&modelBin, sizeof(AssetLib::Model)); dstFile.write((char*)geo.subobjects.data(), sizeof(geo.subobjects[0]) * geo.subobjects.size()); dstFile.write((char*)geo.positions.data(), sizeof(geo.positions[0]) * geo.positions.size()); dstFile.write((char*)geo.texcoords.data(), sizeof(geo.texcoords[0]) * geo.texcoords.size()); dstFile.write((char*)geo.normals.data(), sizeof(geo.normals[0]) * geo.normals.size()); dstFile.write((char*)geo.colors.data(), sizeof(geo.colors[0]) * geo.colors.size()); dstFile.write((char*)geo.tangents.data(), sizeof(geo.tangents[0]) * geo.tangents.size()); dstFile.write((char*)geo.bitangents.data(), sizeof(geo.bitangents[0]) * geo.bitangents.size()); dstFile.write((char*)geo.indices.data(), sizeof(geo.indices[0]) * geo.indices.size()); return true; }
double pivot_weighted(double * v, size_t from, size_t to, double target, double * w, double * csw) { // Rprintf("Entering pivot with len=%d and target=%f\n ", len, target); // RprintV(v, len); size_t len = to-from; if (len > 2) { // pick the pivot, say as the median of the first, middle and last size_t i1 = from, i2 = to-1, i3 = (from + to)/2, ip; if (v[i1] <= v[i2]) { if (v[i2] <= v[i3]) ip = i2; else if (v[i3] >= v[i1]) ip = i3; else ip = i1; } else { if (v[i1] <= v[i3]) ip = i1; else if (v[i2] <= v[i3]) ip = i3; else ip = i2; } // put v[ip] at the end double vp, wp; swap(v[ip], v[to-1], vp); swap(w[ip], w[to-1], wp); // Rprintf(" pivot value: %5.3f, index: %d\n", vp, ip); // pivot everything else size_t bound = from; for (size_t i=from; i<to; i++) if (v[i] < vp) { double temp; swap(v[bound], v[i], temp); swap(w[bound], w[i], temp) bound++; } v[len-1] = v[bound]; v[bound] = vp; w[len-1] = w[bound]; w[bound] = wp; // Update the cumulative sums double sum = from > 0 ? csw[from-1] : 0; for (size_t i=from; i<to; i++) { sum = sum + w[i]; csw[i] = sum; } // Rprintf(" After pivoting: bound:%d and vector: ", bound); // RprintV(v, len); // Did we find the target? double crit = target - bound; // Rprintf(" crit: %5.3f\n", crit); if (fabs(crit) > 1.0) { if (crit < 0) return pivot(v, bound, target); else return pivot(v+bound+1, len-bound-1, target-bound-1); } // Rprintf("vMax(v, bound): %5.3f, vMin(v+bound+1, len-bound-1): %5.3f, vp: %5.3f\n", vMax(v, bound), // vMin(v+bound+1, len-bound-1), vp); if (crit < 0) { double v1 = vMax(v, bound); return (v1 *(-crit) + vp * (1+crit)); } // else double v2 = vMin(v+bound+1, len-bound-1); return (vp * (1-crit) + v2 * crit); } else if (len==2) { // Rprintf(" Short v, returning a direct value.\n"); double v1 = vMin(v, 2); double v2 = vMax(v, 2); if (target < 0) return v1; else if (target > 1) return v2; else return (target * v2 + (1-target) * v1); } else { // Rprintf(" length 1 v, returning a direct value.\n"); return v[0]; } }
HRESULT CCubeCol::CreateBuffer(void) { //여기 HRESULT hr = E_FAIL; m_iVertexStrides = sizeof(VTXCOL); m_iVertexOffsets = 0; D3DXVECTOR3 vMin(-1.f, -1.f, -1.f); D3DXVECTOR3 vMax(1.f, 1.f, 1.f); VTXCOL Vertex[] = { { D3DXVECTOR3(vMin.x, vMax.y, vMin.z), D3DXCOLOR(1,0,0,1) }, { D3DXVECTOR3(vMax.x, vMax.y, vMin.z), D3DXCOLOR(1,0,0,1) }, { D3DXVECTOR3(vMax.x, vMin.y, vMin.z), D3DXCOLOR(1,0,0,1) }, { D3DXVECTOR3(vMin.x, vMin.y, vMin.z), D3DXCOLOR(1,0,0,1) }, { D3DXVECTOR3(vMin.x, vMax.y, vMax.z), D3DXCOLOR(1,0,0,1) }, { D3DXVECTOR3(vMax.x, vMax.y, vMax.z), D3DXCOLOR(1,0,0,1) }, { D3DXVECTOR3(vMax.x, vMin.y, vMax.z), D3DXCOLOR(1,0,0,1) }, { D3DXVECTOR3(vMin.x, vMin.y, vMax.z), D3DXCOLOR(1,0,0,1) }, }; D3D11_BUFFER_DESC vbd; // 버퍼 디스크 = 버퍼의 용도와 크기와 접근권한 ZeroMemory(&vbd, sizeof(vbd)); vbd.Usage = D3D11_USAGE_DEFAULT; // 버퍼는 연산을 위해 필요한 것인대 하드웨어에서 연산이 가능한 객체는 2개가있음 CPU, GPU vbd.ByteWidth = sizeof(VTXCOL) * 8; // 크기 vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // 용도 = 버퍼는 3개가 있음. 버텍스, 인덱스, 콘스턴트 vbd.CPUAccessFlags = 0; vbd.MiscFlags = 0; vbd.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA vBufferData; // 서브리소스는 데이터인대 = 실질적인 값을 의미함 ZeroMemory(&vBufferData, sizeof(D3D11_SUBRESOURCE_DATA)); vBufferData.pSysMem = Vertex; hr = CDevice::GetInstance()->m_pDevice->CreateBuffer(&vbd, &vBufferData, &m_VertexBuffer); if (FAILED(hr)) return E_FAIL; UINT Index[] = { //+x 1, 5, 6, 1, 6, 2, //-x 4, 0, 3, 4, 3, 7, //+y 4, 5, 1, 4, 3, 7, //-y 3, 2, 6, 3, 6, 7, //+z 7, 6, 5, 7, 5, 4, //-z 0, 1, 2, 0, 2, 3, }; m_iIndex = 36; D3D11_BUFFER_DESC ibd; // 권한/크기/용도 ibd.Usage = D3D11_USAGE_DEFAULT; // 권한 ibd.ByteWidth = sizeof(UINT) * m_iIndex; // 크기 ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; // 용도 ibd.CPUAccessFlags = 0; // CPU접근권한 설정 ibd.MiscFlags = 0; ibd.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA iinitData; // 실제 데이터 iinitData.pSysMem = Index; hr = CDevice::GetInstance()->m_pDevice->CreateBuffer(&ibd, &iinitData, &m_IndexBuffer); if (FAILED(hr)) return E_FAIL; //다이렉트9 != 다이렉트11 //다이렉트9 = 컨스턴트 테이블이 존재 수 많은 글로벌 변수가 값은 채워지지 않고 할당만 되어있었음 = 메모리 낭비 //다이렉트11 = 상수는 약속을함 상수 버퍼가 채워지지 않으면 셰이더가 작동하지않음 = 메모리 최적화 D3D11_BUFFER_DESC cbd; // 접근권한 / 용도/ 크기 cbd.Usage = D3D11_USAGE_DEFAULT; cbd.ByteWidth = sizeof(ConstantBuffer); cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbd.CPUAccessFlags = 0; cbd.MiscFlags = 0; cbd.StructureByteStride = 0; hr = CDevice::GetInstance()->m_pDevice->CreateBuffer(&cbd, NULL, &m_ConstantBuffer); /*D3D11_BUFFER_DESC bd; ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_DYNAMIC; // CPU에게 읽기를 할수있는 권한을 주심 bd.ByteWidth = sizeof(ConstantBuffer); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // 라이트의 권한을 주었지 ㅇㅋ? CDevice::GetInstance()->m_pDevice->CreateBuffer(&bd, NULL, &m_ConstantBuffer);*/ if (FAILED(hr)) { MessageBox(NULL, L"System Message", L"Constant Buffer Error", MB_OK); return hr; } return S_OK; }
static bool RecursivelyBuildBSP(CLightBSPNode** ppNode, PrePolyArray& PolyList, CLightBSPPoly** ppBSPPolyList) { //sanity check ASSERT(ppNode); ASSERT(PolyList.GetSize() > 0); //number of polies that lie on the plane uint32 nNumLieOn, nFront, nBack; //first off, find the best splitting plane uint32 nSplitPlane = FindBestSplitPlane(PolyList, nNumLieOn, nFront, nBack); //allocate the new node *ppNode = AllocateBSPNode(nNumLieOn); //check for memory failure if(*ppNode == NULL) return false; //setup the node (*ppNode)->m_vPlaneNorm = PolyList[nSplitPlane]->Normal(); (*ppNode)->m_fPlaneDist = PolyList[nSplitPlane]->Dist(); //create the front, back, and on arrays PrePolyArray Front, Back, On; Front.SetSize(nFront); Back.SetSize(nBack); On.SetSize(nNumLieOn); //now fill up all the lists PVector vNormal = PolyList[nSplitPlane]->Normal(); float fDist = PolyList[nSplitPlane]->Dist(); //index to the coplanar poly offset uint32 nPolyIndex = 0; //indices for the lists uint32 nFrontIndex = 0; uint32 nBackIndex = 0; uint32 nOnIndex = 0; uint32 nType; //now need to count up the split information for(uint32 nTestPoly = 0; nTestPoly < PolyList.GetSize(); nTestPoly++) { if(nTestPoly == nSplitPlane) { On[nOnIndex++] = PolyList[nTestPoly]; (*ppNode)->m_pPolyList[nPolyIndex++] = ppBSPPolyList[PolyList[nTestPoly]->m_Index]; continue; } nType = ClassifyPoly(vNormal, fDist, PolyList[nTestPoly]); if(nType & PLANE_FRONT) Front[nFrontIndex++] = PolyList[nTestPoly]; if(nType & PLANE_BACK) Back[nBackIndex++] = PolyList[nTestPoly]; if(nType == PLANE_ON) { On[nOnIndex++] = PolyList[nTestPoly]; (*ppNode)->m_pPolyList[nPolyIndex++] = ppBSPPolyList[PolyList[nTestPoly]->m_Index]; } } //sanity check ASSERT(nPolyIndex == (*ppNode)->m_nNumPolies); ASSERT(nFrontIndex == nFront); ASSERT(nBackIndex == nBack); ASSERT(nOnIndex == nNumLieOn); //build up the child lists bool bSuccess = true; if(Front.GetSize() > 0) { bSuccess = RecursivelyBuildBSP(&(*ppNode)->m_pFront, Front, ppBSPPolyList); } if(bSuccess && (Back.GetSize() > 0)) { bSuccess = RecursivelyBuildBSP(&(*ppNode)->m_pBack, Back, ppBSPPolyList); } //see if we need to clean up if(!bSuccess) { FreeBSPNode(*ppNode); *ppNode = NULL; return false; } //we need to update the node's bounding sphere. This is done by running through all //the polygons on the plane and generating a bounding box, finding its center, and then //the maximum distance to the points PVector vMin((PReal)MAX_CREAL, (PReal)MAX_CREAL, (PReal)MAX_CREAL); PVector vMax(-vMin); uint32 nCurrPoly; for(nCurrPoly = 0; nCurrPoly < nNumLieOn; nCurrPoly++) { CPrePoly* pPoly = On[nCurrPoly]; for(uint32 nCurrVert = 0; nCurrVert < pPoly->NumVerts(); nCurrVert++) { VEC_MIN(vMin, vMin, pPoly->Pt(nCurrVert)); VEC_MAX(vMax, vMax, pPoly->Pt(nCurrVert)); } } //found the center (*ppNode)->m_vBSphereCenter = ((vMin + vMax) / 2); //now update the radius (*ppNode)->m_fBSphereRadSqr = 0; PReal fDistSqr; for(nCurrPoly = 0; nCurrPoly < nNumLieOn; nCurrPoly++) { CPrePoly* pPoly = On[nCurrPoly]; for(uint32 nCurrVert = 0; nCurrVert < pPoly->NumVerts(); nCurrVert++) { fDistSqr = (pPoly->Pt(nCurrVert) - (*ppNode)->m_vBSphereCenter).MagSqr(); if(fDistSqr > (*ppNode)->m_fBSphereRadSqr) { (*ppNode)->m_fBSphereRadSqr = fDistSqr; } } } //add some padding to the radius to compensate for inaccuracy (*ppNode)->m_fBSphereRadSqr += NODE_RADIUS_PADDING; return bSuccess; }
/*------------------------------------- doThreshAnalysis description: this is the main analysis function. It does some of the analysis, and delegates some responsibility to more specific doThreshAnalysis function input: TaskType &taskType - the struct that tells the function which analyses to perform for this task output: vector<basicStats> - an array of statistics structures for each analyses (e.g., video, audio, etc) */ bool analysis::doThreshAnalysis() { //reset the latencyStats vector latencyStats.clear(); //if for some reason the file has not been read, return if (!mIsOpen) return false; //do the amp latency analysis //the task type struct has a flag for each possible analysis, which tells if //we should perform the analysis basicStats ampStats; if (thisTask.amp.flag) { //the amp analysis does not depend on any specific state, so just do the //analysis on the specified channel based on the latency from the block start ampStats = doThreshAnalysis(thisTask.amp.ch); ampStats.taskName = "Amp "; // add the stats to the stats vector latencyStats.push_back(ampStats); //check for dropped samples on this channel checkDroppedSamples(thisTask.amp.ch); } //do the analysis on each state for the video basicStats vidSystemStats; if (thisTask.vid.flag) { //do the video analysis on the channel and state specified vidSystemStats = doThreshAnalysis(thisTask.vid.ch, thisTask.vid.state, thisTask.vid.stateVal); vidSystemStats.taskName = "VidSys "; latencyStats.push_back(vidSystemStats); checkDroppedSamples(thisTask.vid.ch); } //do the analysis on each state for the audio basicStats audSystemStats; if (thisTask.aud.flag) { audSystemStats = doThreshAnalysis(thisTask.aud.ch, thisTask.aud.state, thisTask.aud.stateVal); audSystemStats.taskName = "AudSys "; latencyStats.push_back(audSystemStats); checkDroppedSamples(thisTask.aud.ch); } //do the processing latency and metronome //first, get the "metronome" stats, the difference in time between each block source time map<string, double*>::iterator it; //an iterator for the states map //declare double vectors for the metronome and processing latencies vector<double> metronomeDiff; vector<double> procLat; //declare variables to track previous values of the stim and source times double stimT, oldStimT, sourceT, oldSourceT, prevSourceT; //get the first values for stim/source times oldStimT = states["StimulusTime"][0]; oldSourceT = prevSourceT = states["SourceTime"][0]; float nMod1 = 0, nMod2 = 0; //loop through the states, starting at the 2nd block, and increase //by the block size for (int i = blockSize; i < nSamples; i += blockSize) { stimT = states["StimulusTime"][i]; sourceT = states["SourceTime"][i]; //nMod1 and nMod2 track the times, which are short (16bit) integers //if the new stim is less than the oldStim, we have wrapped around //and so we must correct for this if (stimT-oldStimT < 0) nMod1++; if (sourceT-oldSourceT < 0) nMod2++; //the processing latency is the difference between the stimulus time and //source time; if we have wrapped the times, the nModX variable corrects this double procDT = ((stimT+nMod1*65535) - (sourceT+nMod2*65535)); //the jitter/metronome is the difference between the current sourceTime //minus the previous source time //additionally, we are putting this in relation to the "theoretical" value, //which is the blockSize, and converting this to ms double jitter = abs(((sourceT+nMod2*65535)-prevSourceT) - blockSize/sampleRate*1000); //add the jitter and processing latencies to their respective arrays metronomeDiff.push_back(jitter); procLat.push_back(procDT); //update stim and source times oldStimT = stimT; oldSourceT = sourceT; prevSourceT = (sourceT+nMod2*65535); } //calculate the stats for the processing latency using our vector helper functions basicStats procStats; procStats.mean = vMean(&procLat); procStats.std = vStd(&procLat); procStats.min = vMin(&procLat); procStats.max = vMax(&procLat); //procStats.vals = procLat; procStats.taskName = "ProcLat "; procStats.desc = "StimulusTime - SourceTime"; //...now do the same for the metronome basicStats metronome; metronome.mean = vMean(&metronomeDiff); metronome.max = vMax(&metronomeDiff); metronome.min = vMin(&metronomeDiff); metronome.std = vStd(&metronomeDiff); metronome.taskName = "Jitter "; metronome.desc = "SourceTime[t+1] - SourceTime[t]"; //add these to the task stats array latencyStats.push_back(metronome); latencyStats.push_back(procStats); //if we did the amp and video latencies, then we can also calculate the //video system latency (actually, the video latency calculate above is the //video system latency, so we use that to find the output latency as: // vidOut = vidSys - amp - procLat) if (thisTask.amp.flag && thisTask.vid.flag) { basicStats vidOutputStats; vidOutputStats.mean = vidSystemStats.mean - ampStats.mean - procStats.mean; vidOutputStats.std = sqrt(pow(vidSystemStats.std,2) + pow(ampStats.std,2) + pow(procStats.std,2)); vidOutputStats.min = vidSystemStats.min - ampStats.min - procStats.min; vidOutputStats.max = vidSystemStats.max - ampStats.max - procStats.max; vidOutputStats.taskName = "VidOut "; vidOutputStats.desc = "Video output latency"; latencyStats.push_back(vidOutputStats); } //same as the video stats above if (thisTask.amp.flag && thisTask.aud.flag) { basicStats audOutputStats; audOutputStats.mean = audSystemStats.mean - ampStats.mean - procStats.mean; audOutputStats.std = sqrt(pow(audSystemStats.std,2) + pow(ampStats.std,2) + pow(procStats.std,2)); audOutputStats.min = audSystemStats.min - ampStats.min - procStats.min; audOutputStats.max = audSystemStats.max - ampStats.max - procStats.max; audOutputStats.taskName = "AudOut "; audOutputStats.desc = "Audio output latency"; latencyStats.push_back(audOutputStats); } //return our stats return true; }