void CTexelNormalMethod::GenerateTexel(size_t iTexel, CConversionMeshInstance* pMeshInstance, CConversionFace* pFace, CConversionVertex* pV1, CConversionVertex* pV2, CConversionVertex* pV3, raytrace::CTraceResult* tr, const Vector& vecUVPosition, raytrace::CRaytracer* pTracer) { CConversionFace* pHitFace = tr->m_pMeshInstance->GetMesh()->GetFace(tr->m_iFace); Vector vecHitNormal = pHitFace->GetNormal(tr->m_vecHit, tr->m_pMeshInstance); // Build rotation matrix Matrix4x4 mObjectToTangent; Vector t = pFace->GetBaseVector(vecUVPosition, 0, pMeshInstance); Vector b = pFace->GetBaseVector(vecUVPosition, 1, pMeshInstance); Vector n = pFace->GetBaseVector(vecUVPosition, 2, pMeshInstance); mObjectToTangent.SetForwardVector(t); mObjectToTangent.SetUpVector(b); mObjectToTangent.SetRightVector(n); mObjectToTangent.InvertRT(); Vector vecTangentNormal = mObjectToTangent*vecHitNormal; m_pGenerator->GetParallelizer()->LockData(); m_avecNormalValues[iTexel] += vecTangentNormal; m_pGenerator->MarkTexelUsed(iTexel); m_pGenerator->GetParallelizer()->UnlockData(); }
void CTexelAOMethod::GenerateTexel(size_t iTexel, CConversionMeshInstance* pMeshInstance, CConversionFace* pFace, CConversionVertex* pV1, CConversionVertex* pV2, CConversionVertex* pV3, raytrace::CTraceResult* tr, const Vector& vecUVPosition, raytrace::CRaytracer* pTracer) { CConversionFace* pHitFace = tr->m_pMeshInstance->GetMesh()->GetFace(tr->m_iFace); Vector vecHitNormal = pHitFace->GetNormal(tr->m_vecHit, tr->m_pMeshInstance); // Build rotation matrix Matrix4x4 m; m.SetOrientation(vecHitNormal); // Turn it sideways so that pitch 90 is up Matrix4x4 m2; m2.SetAngles(EAngle(-90, 0, 0)); m *= m2; //SMAKWindow()->AddDebugLine(vecUVPosition + pFace->GetNormal()*0.01f, vecUVPosition + vecNormal*0.5f, Color(0, 0, 255)); float flHits = 0; float flTotalHits = 0; for (size_t x = 0; x < m_iSamples/2; x++) { float flRandom = 0; if (m_bRandomize) flRandom = RemapVal((float)(rand()%10000), 0, 10000.0f, -0.5f, 0.5f); float flPitch = RemapVal(cos(RemapVal((float)x+flRandom, 0, (float)m_iSamples/2, 0, (float)M_PI/2)), 0, 1, 90, 0); float flWeight = sin(flPitch * M_PI/180); for (size_t y = 0; y <= m_iSamples; y++) { flRandom = 0; if (m_bRandomize) flRandom = RemapVal((float)(rand()%10000), 0, 10000.0f, -0.5f, 0.5f); float flYaw = RemapVal((float)y+flRandom, 0, (float)m_iSamples, -180, 180); Vector vecDir = AngleVector(EAngle(flPitch, flYaw, 0)); // Transform relative to the triangle's normal Vector vecRay = m * vecDir; flTotalHits += flWeight; //SMAKWindow()->AddDebugLine(vecUVPosition + pFace->GetNormal()*0.01f, vecUVPosition + vecRay.Normalized()*0.1f, vecDir); raytrace::CTraceResult tr2; if (pTracer->Raytrace(Ray(tr->m_vecHit + vecHitNormal*0.01f, vecRay), &tr2)) { float flDistance = (tr2.m_vecHit - tr->m_vecHit).Length(); if (m_flRayFalloff < 0) flHits += flWeight; else flHits += flWeight * (1/pow(2, flDistance/m_flRayFalloff)); } else if (m_bGroundOcclusion && vecRay.y < 0) { // The following math is basically a plane-ray intersection algorithm, // with shortcuts made for the assumption of an infinite plane facing straight up. Vector n = Vector(0,1,0); float a = -(vecUVPosition.y - pMeshInstance->m_pParent->m_oExtends.m_vecMins.y); float b = vecRay.y; float flDistance = a/b; if (flDistance < 1e-4f || m_flRayFalloff < 0) flHits += flWeight; else flHits += flWeight * (1/pow(2, flDistance/m_flRayFalloff)); } } } // One last ray directly up, it is skipped in the above loop so it's not done 10 times. Vector vecDir = AngleVector(EAngle(90, 0, 0)); // Transform relative to the triangle's normal Vector vecRay = m * vecDir; //RenderSceneFromPosition(vecUVPosition, vecRay, pFace); flTotalHits++; //SMAKWindow()->AddDebugLine(vecUVPosition + pFace->GetNormal()*0.01f, vecUVPosition + vecRay.Normalized()*0.2f, vecDir); raytrace::CTraceResult tr2; if (pTracer->Raytrace(Ray(tr->m_vecHit + vecHitNormal*0.01f, vecRay), &tr2)) { float flDistance = (tr2.m_vecHit - tr->m_vecHit).Length(); if (m_flRayFalloff < 0) flHits += 1; else flHits += (1/pow(2, flDistance/m_flRayFalloff)); } else if (m_bGroundOcclusion && vecRay.y < 0) { // The following math is basically a plane-ray intersection algorithm, // with shortcuts made for the assumption of an infinite plane facing straight up. float a = -(tr->m_vecHit.y - pMeshInstance->m_pParent->m_oExtends.m_vecMins.y); float b = vecRay.y; float flDistance = a/b; if (flDistance < 1e-4f || m_flRayFalloff < 0) flHits += 1; else flHits += (1/pow(2, flDistance/m_flRayFalloff)); } float flShadowValue = 1 - ((float)flHits / (float)flTotalHits); // Mutex may be dead, try to bail before. if (m_pGenerator->IsStopped()) return; m_pGenerator->GetParallelizer()->LockData(); m_avecShadowValues[iTexel] += Vector(flShadowValue, flShadowValue, flShadowValue); m_aiShadowReads[iTexel]++; m_pGenerator->MarkTexelUsed(iTexel); m_pGenerator->GetParallelizer()->UnlockData(); }