//---------------------------------------------------------------------------- bool Bound::TestIntersection (const Bound& bound, float tmax, const AVector& velocity0, const AVector& velocity1) const { if (bound.GetRadius() == 0.0f || GetRadius() == 0.0f) { return false; } AVector relVelocity = velocity1 - velocity0; // 相对速度 AVector cenDiff = bound.mCenter - mCenter; // 相对位移 float a = relVelocity.SquaredLength(); float c = cenDiff.SquaredLength(); float rSum = bound.mRadius + mRadius; float rSumSqr = rSum*rSum; if (a > 0.0f) { float b = cenDiff.Dot(relVelocity); if (b <= 0.0f) { if (-tmax*a <= b) { return a*c - b*b <= a*rSumSqr; } else { return tmax*(tmax*a + 2.0f*b) + c <= rSumSqr; } } } return c <= rSumSqr; }
//---------------------------------------------------------------------------- bool InputPushTransformController::IsSmallTransScope() { AVector smallScope = mMaxPosSmall - mMinPosSmall; float lengthSquare = smallScope.SquaredLength(); return 0.0f != lengthSquare; }
//---------------------------------------------------------------------------- void Fluids3D::UpdateIndexBuffer () { VertexBufferAccessor vba(mCube); APoint camPos = mCamera->GetPosition(); const int numTriangles = mNumIndices/3; int* currentIndex = mIndices; mTriangles.clear(); for (int t = 0; t < numTriangles; ++t) { Triangle tri; tri.mIndex0 = *currentIndex++; tri.mIndex1 = *currentIndex++; tri.mIndex2 = *currentIndex++; #ifdef USE_PARTICLES float alpha = vba.Color<Float4>(0, tri.mIndex0)[3]; if (alpha == 0.0f) { continue; } #else float alpha0 = vba.Color<Float4>(0, tri.mIndex0)[3]; float alpha1 = vba.Color<Float4>(0, tri.mIndex1)[3]; float alpha2 = vba.Color<Float4>(0, tri.mIndex2)[3]; if (alpha0 == 0.0f && alpha1 == 0.0f && alpha2 == 0.0f) { continue; } #endif Vector3f scaledCenter = vba.Position<Vector3f>(tri.mIndex0) + vba.Position<Vector3f>(tri.mIndex1) + vba.Position<Vector3f>(tri.mIndex2); APoint output = mCube->WorldTransform*APoint(scaledCenter); AVector diff = output - camPos; tri.mNegSqrDistance = -diff.SquaredLength(); mTriangles.insert(tri); } IndexBuffer* ibuffer = mCube->GetIndexBuffer(); int* indices = (int*)ibuffer->GetData(); ibuffer->SetNumElements(3*(int)mTriangles.size()); std::multiset<Triangle>::iterator iter = mTriangles.begin(); std::multiset<Triangle>::iterator end = mTriangles.end(); for (/**/; iter != end; ++iter) { *indices++ = iter->mIndex0; *indices++ = iter->mIndex1; *indices++ = iter->mIndex2; } mRenderer->Update(ibuffer); }
//---------------------------------------------------------------------------- bool Bound::TestIntersection (const Bound& bound) const { if (bound.GetRadius() == 0.0f || GetRadius() == 0.0f) { return false; } // 静态相交检测 AVector diff = mCenter - bound.mCenter; float rSum = mRadius + bound.mRadius; return diff.SquaredLength() <= rSum*rSum; }
//----------------------------------------------------------------------------- void Scene::GetRangeActors (std::vector<Actor*> &actors, const APoint ¢er, float radius, bool useActorSelfRadius, const std::bitset<16> &bits) { actors.clear(); if (SMT_NONE == mSceneManageType) { for (int i=0; i<GetNumActors(); i++) { Actor *actor = GetActor(i); if (!actor->IsVisible()) continue; const APoint &pos = actor->GetPosition(); AVector dir = pos - center; float lengthSquare = dir.SquaredLength(); float adjustLength = radius; if (useActorSelfRadius) { adjustLength += actor->GetSelfRadius(); } if (lengthSquare < adjustLength*adjustLength) { if (actor->IsContainAllBits(bits)) { actors.push_back(actor); } } } } else { if (SMT_OCTREE == mSceneManageType) { } else if (SMT_CELL2D == mSceneManageType) { mCellSpace->CalculateNeighbors(actors, center, radius, useActorSelfRadius, bits); } } }
//---------------------------------------------------------------------------- float CurveSegment::Curvature (float u) const { AVector velocity = PU(u); float speedSqr = velocity.SquaredLength(); if (speedSqr >= Mathf::ZERO_TOLERANCE) { AVector acceleration = PUU(u); AVector cross = velocity.Cross(acceleration); float numer = cross.Length(); float denom = Mathf::Pow(speedSqr, 1.5f); return numer/denom; } else { // Curvature is indeterminate, just return 0. return 0.0f; } }
//---------------------------------------------------------------------------- float CurveSegment::Torsion (float u) const { AVector velocity = PU(u); AVector acceleration = PUU(u); AVector cross = velocity.Cross(acceleration); float denom = cross.SquaredLength(); if (denom >= Mathf::ZERO_TOLERANCE) { AVector jerk = PUUU(u); float numer = cross.Dot(jerk); return numer/denom; } else { // Torsion is indeterminate, just return 0. return 0.0f; } }
//---------------------------------------------------------------------------- void Scene::GetRangeActors(std::vector<Actor*> &actors, const APoint ¢er, float radius, bool useActorSelfRadius, const std::bitset<PX2_ACTOR_BS_SIZE> &bits) { actors.clear(); if (SMT_NONE == mSceneManageType) { for (int i = 0; i < GetNumChildren(); i++) { Actor *actor = DynamicCast<Actor>(GetChild(i)); if (!actor->IsShow()) continue; const APoint &pos = actor->LocalTransform.GetTranslate(); AVector dir = pos - center; float lengthSquare = dir.SquaredLength(); float adjustLength = radius; if (useActorSelfRadius) { adjustLength += actor->GetRadius(); } if (lengthSquare < adjustLength*adjustLength) { if (actor->IsContainAllBits(bits)) { actors.push_back(actor); } } } } else { if (SMT_OCTREE == mSceneManageType) { } else if (SMT_CELL2D == mSceneManageType) { mCellSpace->CalculateNeighbors(actors, center, radius, useActorSelfRadius, bits); } } }
//----------------------------------------------------------------------------- void CellSpace::CalculateNeighbors(std::vector<Actor*> &actors, const APoint &targetPos, float queryRadius, bool useActorSelfRadius, const std::bitset<PX2_ACTOR_BS_SIZE> &bits) { AVector radiusDir = AVector(queryRadius, queryRadius, queryRadius); APoint min = targetPos - radiusDir; APoint max = targetPos + radiusDir; AxisAlignedBox3f queryBox(min, max); std::vector<Cell>::iterator curCell = mCells.begin(); for (; curCell != mCells.end(); ++curCell) { if (curCell->AlignedBox.TestIntersection(queryBox) && !curCell->Members.empty()) { std::list<Actor*>::iterator it = curCell->Members.begin(); for (; it != curCell->Members.end(); ++it) { if (!(*it)->IsShow()) continue; AVector disDir = (*it)->LocalTransform.GetTranslate() - targetPos; float distanceSquared = disDir.SquaredLength(); float adjustDist = queryRadius; if (useActorSelfRadius) { adjustDist += (*it)->GetRadius(); } if (distanceSquared <= adjustDist*adjustDist) { if ((*it)->IsContainAllBits(bits)) { actors.push_back(*it); } } } } } }
//---------------------------------------------------------------------------- void Bound::GrowToContain (const Bound& bound) { if (bound.GetRadius() == 0.0f) { // The node is a dummy node and cannot affect growth. return; } if (GetRadius() == 0.0f) { mCenter = bound.GetCenter(); mRadius = bound.GetRadius(); return; } AVector centerDiff = bound.mCenter - mCenter; float lengthSqr = centerDiff.SquaredLength(); float radiusDiff = bound.mRadius - mRadius; float radiusDiffSqr = radiusDiff*radiusDiff; if (radiusDiffSqr >= lengthSqr) { if (radiusDiff >= 0.0f) { mCenter = bound.mCenter; mRadius = bound.mRadius; } return; } float length = Mathf::Sqrt(lengthSqr); if (length > Mathf::ZERO_TOLERANCE) { float coeff = (length + radiusDiff)/(2.0f*length); mCenter += coeff*centerDiff; } mRadius = 0.5f*(length + mRadius + bound.mRadius); }
//---------------------------------------------------------------------------- void VolumeTextures::CreateScene () { mScene = new0 Node(); mAlphaState = new0 AlphaState(); mAlphaState->BlendEnabled = true; mRenderer->SetOverrideAlphaState(mAlphaState); mCullState = new0 CullState(); mCullState->Enabled = false; mRenderer->SetOverrideCullState(mCullState); // Create the grid of square meshes. const int numSlices = 64; const int numSamples = 32; // The vertex format that is shared by all square meshes. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); // The index buffer that is shared by all square meshes. int numIndices = 6*(numSamples-1)*(numSamples-1); IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); int* indices = (int*)ibuffer->GetData(); for (int i1 = 0; i1 < numSamples - 1; ++i1) { for (int i0 = 0; i0 < numSamples - 1; ++i0) { int v0 = i0 + numSamples * i1; int v1 = v0 + 1; int v2 = v1 + numSamples; int v3 = v0 + numSamples; *indices++ = v0; *indices++ = v1; *indices++ = v2; *indices++ = v0; *indices++ = v2; *indices++ = v3; } } // Create the volume texture. Three Gaussian distributions are used for // the RGB color channels. The alpha channel is constant. const int bound = 64; Texture3D* texture = new0 Texture3D(Texture::TF_A8R8G8B8, bound, bound, bound, 1); unsigned char* data = (unsigned char*)texture->GetData(0); const float mult = 1.0f/(bound - 1.0f); const float rParam = 0.01f; const float gParam = 0.01f; const float bParam = 0.01f; const float extreme = 8.0f; APoint rCenter( 0.5f*extreme, 0.0f, 0.0f); APoint gCenter(-0.5f*extreme, -0.5f*extreme, 0.0f); APoint bCenter(-0.5f*extreme, +0.5f*extreme, 0.0f); unsigned char commonAlpha = 12; APoint point; for (int z = 0; z < bound; ++z) { point[2] = -extreme + 2.0f*extreme*mult*z; for (int y = 0; y < bound; ++y) { point[1] = -extreme + 2.0f*extreme*mult*y; for (int x = 0; x < bound; ++x) { point[0] = -extreme + 2.0f*extreme*mult*x; AVector diff = point - rCenter; float sqrLength = diff.SquaredLength(); float rGauss = 1.0f - rParam*sqrLength; if (rGauss < 0.0f) { rGauss = 0.0f; } diff = point - gCenter; sqrLength = diff.SquaredLength(); float gGauss = 1.0f - gParam*sqrLength; if (gGauss < 0.0f) { gGauss = 0.0f; } diff = point - bCenter; sqrLength = diff.SquaredLength(); float bGauss = 1.0f - bParam*sqrLength; if (bGauss < 0.0f) { bGauss = 0.0f; } *data++ = (unsigned char)(255.0f*bGauss); *data++ = (unsigned char)(255.0f*gGauss); *data++ = (unsigned char)(255.0f*rGauss); *data++ = commonAlpha; } } } // The volume texture effect that is shared by all square meshes. std::string effectFile = Environment::GetPathR("VolumeTextures.wmfx"); VolumeTextureEffect* effect = new0 VolumeTextureEffect(effectFile); VisualEffectInstance* instance = effect->CreateInstance(texture); // The grid of squares. const int numVertices = numSamples*numSamples; float inv = 1.0f/(numSamples - 1.0f); VertexBufferAccessor vba; for (int slice = 0; slice < numSlices; ++slice) { VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); vba.ApplyTo(vformat, vbuffer); float w = slice/(numSlices - 1.0f); float z = 2.0f*w - 1.0f; for (int i1 = 0, i = 0; i1 < numSamples; ++i1) { float v = i1*inv; float y = 2.0f*v - 1.0f; for (int i0 = 0; i0 < numSamples; ++i0, ++i) { float u = i0*inv; float x = 2.0f*u - 1.0f; vba.Position<Float3>(i) = Float3(x, y, z); vba.TCoord<Float3>(0, i) = Float3(u, v, w); } } TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer); mesh->SetEffectInstance(instance); mScene->AttachChild(mesh); } }