Comments (13)
The first thing to do is check that your ModelMesh
has a non-zero bounding volume. The modern SDKMESH exporter and CMO mesh pipeline in Visual Studio should be creating a valid sphere bound, but there are some older SDKMESH models that are missing valid bounds. Because the SDKMESH
does not contain a bounding sphere, one is created at load time from the bounding box.
Note that the center will not necessarily be (0,0,0) in model coordinates because this is not the most efficient sphere bound. The algorithm in DirectXMath's
BoundingSphere::CreateFromPoints
for example is from Ritter, Jack, An Efficient Bounding Sphere, Graphics Gems, Academic Press, 1990, p. 301-303, code: p. 723-725.
The code you provide is doing some really strange stuff with the center of the bounding box. You create a translation based on the bounding sphere center, and then transform the bounding box by that translation. The result is meaningless.
All you really need to do is transform the BoundingSphere
by the same transform as you use for rendering the model. If you want to do collision in world-space, that would just be the 'world' matrix, not the camera's view & projection matrices.
XMMATRIX modelWorld = ...;
BoundingSphere worldSphere;
m_bounding.Transform(worldSphere, modelWorld);
BTW, for debugging collision geometry, you should take a look at DebugDraw
m_batch = std::make_unique<PrimitiveBatch<VertexPositionColor>>(context);
m_effect = std::make_unique<BasicEffect>(device);
m_effect->SetVertexColorEnabled(true);
{
void const* shaderByteCode;
size_t byteCodeLength;
m_effect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength);
DX::ThrowIfFailed(
device->CreateInputLayout(
VertexPositionColor::InputElements, VertexPositionColor::InputElementCount,
shaderByteCode, byteCodeLength,
m_layout.ReleaseAndGetAddressOf()));
}
...
XMMATRIX modelWorld = ...;
XMMATRIX view = m_Camera.ViewMatrix();
XMMATRIX proj = m_Camera.ProjectionMatrix();
m_Tree->Draw( context, *m_states, modelWorld, view, proj);
#ifdef _DEBUG
// Draws an outline of the bounding volume over the model
context->OMSetBlendState(m_states->Opaque(), nullptr, 0xFFFFFFFF);
context->OMSetDepthStencilState(m_states->DepthNone(), 0);
context->RSSetState(m_states->CullNone());
m_effect->Apply(context);
context->IASetInputLayout(m_layout.Get());
m_batch->Begin();
m_effect->SetView(view);
m_effect->SetProjection(proj);
BoundingSphere worldSphere;
m_bounding.Transform(worldSphere, modelWorld);
DX::Draw(m_batch.get(), worldSphere);
m_batch->End();
#endif
from directxtk.
It's in the link I gave you. DebugDraw.h and DebugDraw.cpp.
from directxtk.
I have the following code, but the sphere is translated and its not surrounding the tree. its translated behind it.
here is how I'm rendering it
XMMATRIX treeTranslate = XMMatrixTranslation(100, -100, 112);
// Convert rotation into radians.
float angle = atan2(100 - m_Camera.Position().x, 112 - m_Camera.Position().z) * (180.0 / XM_PI);
float treeRot = (float)angle * 0.0174532925f;
XMMATRIX treeRotation = XMMatrixRotationY(treeRot);
XMMATRIX treeWorld = treeRotation*treeTranslate; // THIS IS THE IMPORTANT WORLD, THE ROTATION IS IMPORTANT TO INCLUDE
m_Tree->Draw(m_Graphics.getContext(), states, treeWorld, m_Graphics.getViewMatrix(),
m_Camera.ProjectionMatrix());
m_bounding = m_Tree->meshes.at(0)->boundingSphere;
m_batch->Begin();
m_bounding.Transform(m_bounding, treeWorld);
m_effect->SetView(m_Camera.ViewMatrix());
m_effect->SetProjection(m_Camera.ProjectionMatrix());
Draw(m_batch.get(), m_bounding, Colors::Red);
m_batch->End();
from directxtk.
What's the original values in m_Tree->meshes.at(0)->boundingSphere
?
from directxtk.
m_bounding {Center={x=0.00674819946 y=72.5237503 z=-0.932399750 } Radius=110.144882 } DirectX::BoundingSphere
from directxtk.
Ok. It looks valid at least.
That said, m_bounding.Transform(m_bounding, treeWorld);
means you are modifying the bounding sphere every frame you render which is not what you want to do. Make a temporary:
BoundingSphere treeSphere;
m_bounding.Transform(treeSphere, treeWorld);
m_effect->SetView(m_Camera.ViewMatrix());
m_effect->SetProjection(m_Camera.ProjectionMatrix());
Draw(m_batch.get(), treeSphere, Colors::Red);
m_batch->End();
from directxtk.
still the sphere is in wrong place
from directxtk.
Sure, but we are getting closer.
Check the values of m_bounding
, treeSphere
, and treeWorld
to make sure they make sense to you.
Also, what's the value of m_Tree->meshes.at(0)->boundingBox
?
What format is your model loading from?
from directxtk.
I use the directx sdkmesh, converted from an obj file.
m_bounding = {Center={x=0.00674819946 y=72.5237503 z=-0.932399750 } Radius=110.144882 }
treeSphere = {Center={x=99.1690521 y=-27.4762497 z=111.576981 } Radius=110.144882 }
tree world
from directxtk.
Bounding box :
box = {Center={x=0.00674819946 y=72.5237503 z=-0.932399750 } Extents={x=58.6604500 y=73.0773544 z=57.8838997 } }
from directxtk.
here is how I do the picking, which is incorrect due to the bounding sphere calculation is wrong, do you find a problem with it ?
void GameApp::Pick(int sx, int sy, XMVECTOR & pickRayInWorldSpacePos, XMVECTOR &pickRayInWorldSpaceDir)
{
XMVECTOR pickRayInViewSpaceDir = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
XMVECTOR pickRayInViewSpacePos = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
float PRVecX, PRVecY, PRVecZ;
XMFLOAT4X4 tmp;
XMStoreFloat4x4(&tmp, m_Camera.ProjectionMatrix());
//Transform 2D pick position on screen space to 3D ray in View space
PRVecX = (((2.0f * sx) / 784) - 1) / tmp.m[0][0];
PRVecY = -(((2.0f * sy) / 562) - 1) / tmp.m[1][1];
PRVecZ = 1.0f; //View space's Z direction ranges from 0 to 1, so we set 1 since the ray goes "into" the screen
pickRayInViewSpaceDir = XMVectorSet(PRVecX, PRVecY, PRVecZ, 0.0f);
//Uncomment this line if you want to use the center of the screen (client area)
//to be the point that creates the picking ray (eg. first person shooter)
//pickRayInViewSpaceDir = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
// Transform 3D Ray from View space to 3D ray in World space
XMMATRIX pickRayToWorldSpaceMatrix;
XMVECTOR matInvDeter; //We don't use this, but the xna matrix inverse function requires the first parameter to not be null
pickRayToWorldSpaceMatrix = XMMatrixInverse(&matInvDeter, m_Camera.ViewMatrix()); //Inverse of View Space matrix is World space matrix
pickRayInWorldSpacePos = XMVector3TransformCoord(pickRayInViewSpacePos, pickRayToWorldSpaceMatrix);
pickRayInWorldSpaceDir = XMVector3TransformNormal(pickRayInViewSpaceDir, pickRayToWorldSpaceMatrix);
pickRayInWorldSpaceDir = XMVector3Normalize(pickRayInWorldSpaceDir);
float dist;
if (m_bounding.Intersects(pickRayInWorldSpacePos, pickRayInWorldSpaceDir, dist) == true)
{
m_Picked++;
}
}
from directxtk.
its fixed, I was not applying the effect.
but I have another problem, as shown in the image the sphere is large and doesn't surround the tree, how would I scale it ?
from directxtk.
That makes more sense :)
The issue here is that the bounding sphere is not a particularly tight bound because of the way it is created. Try picking against the boundingBox
instead (there's a DebugDraw for the box) and see if that's a better bound for your model.
from directxtk.
Related Issues (20)
- Retire legacy Xbox One XDK support
- NonPremultiplied has to be used in the Begin() function. HOT 1
- App.cpp and App.h for UWP DeviceResources HOT 1
- xaudio2 XAUDIO2_E_DEVICE_INVALIDATED HRESULT not handled HOT 16
- Make use of C++/WinRT when building for C++17
- ARM64 version of xwbtool HOT 3
- `MapGuard` undefined behavior after move HOT 3
- DirectX Tool Kit for DX9
- DrawLine line thickness HOT 1
- Mesh Outline Effect HOT 2
- Point Light Shader HOT 2
- Clarify required WinSDK version HOT 2
- Hard fps lock to refresh rate value in fullscreen games - Win11 22H2 (DX11) HOT 2
- XWBtool makes all wav files the same name after repackaging HOT 5
- Audio: how to set distance attenuation/fall-off? HOT 4
- darker images loading HOT 1
- Request/question: Add a Vector4/floating point overload for the spritebatch's draw function
- undefined data type in PostProcess method HOT 3
- Aa
- Should Mouse use WM_MOUSELEAVE for Win32 raw input
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from directxtk.