Creating spherical meshes with Direct x? - c++

How do you go about creating a sphere with meshes in Direct-x? I'm using C++ and the program will be run on windows, only.
Everything is currently rendered through an IDiRECT3DDEVICE9 object.

You could use the D3DXCreateSphere function.

There are lots of ways to create a sphere.
One is to use polar coordinates to generate slices of the sphere.
struct Vertex
{
float x, y, z;
float nx, ny, nz;
};
Given that struct you'd generate the sphere as follows (I haven't tested this so I may have got it slightly wrong).
std::vector< Vertex > verts;
int count = 0;
while( count < numSlices )
{
const float phi = M_PI / numSlices;
int count2 = 0;
while( count2 < numSegments )
{
const float theta = M_2PI / numSegments
const float xzRadius = fabsf( sphereRadius * cosf( phi ) );
Vertex v;
v.x = xzRadius * cosf( theta );
v.y = sphereRadius * sinf( phi );
v.z = xzRadius * sinf( theta );
const float fRcpLen = 1.0f / sqrtf( (v.x * v.x) + (v.y * v.y) + (v.z * v.z) );
v.nx = v.x * fRcpLen;
v.ny = v.y * fRcpLen;
v.nz = v.z * fRcpLen;
verts.push_back( v );
count2++;
}
count++;
}
This is how D3DXCreateSphere does it i believe. Of course the code above does not form the faces but thats not a particularly complex bit of code if you set your mind to it :)
The other, and more interesting in my opinion, way is through surface subdivision.
If you start with a cube that has normals defined the same way as the above code you can recursively subdivide each side. Basically you find the center of the face. Generate a vector from the center to the new point. Normalise it. Push the vert out to the radius of the sphere as follows (Assuming v.n* is the normalised normal):
v.x = v.nx * sphereRadius;
v.y = v.ny * sphereRadius;
v.z = v.nz * sphereRadius;
You then repeat this process for the mid point of each edge of the face you are subdividing.
Now you can split each face into 4 new quadrilateral faces. You can then subdivide each of those quads into 4 new quads and so on until you get to the refinement level you require.
Personally I find this process provides a nicer vertex distribution on the sphere than the first method.

Related

OpenGL Spaceship thruster is not circular at base

I am developing a space shooter game using OpenGL. Trying to create a thruster effect for the player's spaceship using particles. I am facing a problem where the base of the thruster is not circular under some angles of the spaceship. You can see the effect in the video.
This is the code for calculating the circular base :
float random = fmod(static_cast<float>(rand()) / 100.0, mSize);
glm::vec3 radius = (mUp * random) + (mRight * random);
float angle = (float)i / (float)mNumOfInstances * 360.0f;
float x = mPos.x + glm::cos(angle) * radius.x;
float y = mPos.y + glm::sin(angle) * radius.y;
float z = mPos.z + glm::cos(angle) * radius.z;
particle.Position = glm::vec3(x, y, z);
Can someone suggest any corrections to this code to fix the problem?
The solution was the following for anyone having the same problem:
glm::vec3 up = (mUp * random);
glm::vec3 right = (mRight * random);
particle.Position = mPos + glm::cos(angle) * up + sin(angle) * right;
mUp is the Up vector, mRight is the right vector of the spaceship, angle is the angle for the specific point (0-360) and random is a random radius because I want a filled circle.

Check for every triangle of a mesh if it intersects triangle of another mesh

I use vector storing vertices data needed to draw a sphere. The question is, how do I know which three vertices build a triangle and how do I iterate through every single triangle of one mesh to check if it intersects with a triangle of another 3d mesh.
Here is how I populate vector 'vertices' with data:
vector<GLfloat> vertices;
float const R = 1.0f / (float)(rings - 1);
float const S = 1.0f / (float)(sectors - 1);
unsigned int r, s;
vertices.resize(rings * sectors * 3);
vector<GLfloat>::iterator v = vertices.begin();
for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++)
{
float const x = sinf(M_PI * r * R) * cosf(2 * M_PI * s * S);
float const y = sinf(-M_PI_2 + M_PI * r * R );
float const z = sinf(2.0f * M_PI * s * S) * sinf(M_PI * r * R );
*v++ = x * radius;
*v++ = y * radius;
*v++ = z * radius;
}
You might wonder, if I'm about to check for collisions between 2 spheres, why I don't use their radii instead. This is because I intend to use more complex shapes in future, where this simple method won't be of any use.
For the first question you should look at this answer, i think it answers it
procedurally generate a sphere mesh
For the second part of your problem you can always use spatial partitioning to subdivide your space and then iterate over faces in each sup-space, here is a detailed answer i gave earlier
intersection of two triangle meshes

Determine position in front of quaternion with GLM?

Is there a way to calculate the XYZ position in front of a quaternion (XYZW) rotation, preferably using GLM?
I know the Quat rotation and the Position of the object I want to calculate the position in front of.
I know how to calculate the position in front of a rotation matrix where you have a Front vector, Up vector and Right vector, but in this case I only have XYZW values (where W is always 0, I never see it becomming 1..?)
In very short:
The data I have: Quat (X Y Z W) and Position(X Y Z) and I want to calculate PositionInFront(Position, Quat, Distance, &X, &Y, &Z)
How to accomplish this goal?
I tried a cast to 3x3matrix and perform the Up,Right,Front (because a 3x3 matrix cast is these values, right?) calculations but they do not return the correct positions.
Or would it be possible to determine the objects Z Angle? (rotation around world Z / height axis only)
It seemed that there were 2 more quaternion structures for the vehicle which I forgot to use. and those 3 are the complete set needed for the Front,Right,Up calculation formula:
float offX = 10.0f;
float offY = 0.0f;
float offZ = 0.0f;
float x = offX * info.Rotation.Front.x + offY * info.Rotation.Right.x + offZ * info.Rotation.Up.x + info.Pos.x;
float y = offX * info.Rotation.Front.y + offY * info.Rotation.Right.y + offZ * info.Rotation.Up.y + info.Pos.y;
float z = offX * info.Rotation.Front.z + offY * info.Rotation.Right.z + offZ * info.Rotation.Up.z + info.Pos.z;
float Angle = (atan2(x-info.Pos.x, y-info.Pos.y) * 180.0f / PI);

Find mouse world-coordinates (3D) on a quadtree heightmaped terrain

I'm trying to find the mouse position in world coordinates but am having trouble finding the right code. At the moment I use this to determine the ray:
float pointX, pointY;
D3DXMATRIX projectionMatrix, viewMatrix, inverseViewMatrix, worldMatrix, translateMatrix, inverseWorldMatrix;
D3DXVECTOR3 direction, origin, rayOrigin, rayDirection;
bool intersect, result;
// Move the mouse cursor coordinates into the -1 to +1 range.
pointX = ((2.0f * (float)mouseX) / (float)m_screenWidth) - 1.0f;
pointY = (((2.0f * (float)mouseY) / (float)m_screenHeight) - 1.0f) * -1.0f;
// Adjust the points using the projection matrix to account for the aspect ratio of the viewport.
m_Direct3D->GetProjectionMatrix(projectionMatrix);
pointX = pointX / projectionMatrix._11;
pointY = pointY / projectionMatrix._22;
// Get the inverse of the view matrix.
m_Camera->GetViewMatrix(viewMatrix);
D3DXMatrixInverse(&inverseViewMatrix, NULL, &viewMatrix);
// Calculate the direction of the picking ray in view space.
direction.x = (pointX * inverseViewMatrix._11) + (pointY * inverseViewMatrix._21) + inverseViewMatrix._31;
direction.y = (pointX * inverseViewMatrix._12) + (pointY * inverseViewMatrix._22) + inverseViewMatrix._32;
direction.z = (pointX * inverseViewMatrix._13) + (pointY * inverseViewMatrix._23) + inverseViewMatrix._33;
// Get the origin of the picking ray which is the position of the camera.
origin = m_Camera->GetPosition();
This gives me the origin and direction of the ray.
But...
I use a custom mesh (not the one from directX) with a heightmap, separated into quadtrees and I don't know if my logic is correct, I tried using the frustum to determine which nodes in the quadtree are visible and so do the checking intersection of triangles only on those nodes, here is this code:
Note* m_mousepos is a vector.
bool QuadTreeClass::getTriangleRay(NodeType* node, FrustumClass* frustum, ID3D10Device* device, D3DXVECTOR3 vPickRayDir, D3DXVECTOR3 vPickRayOrig){
bool result;
int count, i, j, indexCount;
unsigned int stride, offset;
float fBary1, fBary2;
float fDist;
D3DXVECTOR3 v0, v1, v2;
float p1, p2, p3;
// Check to see if the node can be viewed.
result = frustum->CheckCube(node->positionX, 0.0f, node->positionZ, (node->width / 2.0f));
if(!result)
{
return false;
}
// If it can be seen then check all four child nodes to see if they can also be seen.
count = 0;
for(i=0; i<4; i++)
{
if(node->nodes[i] != 0)
{
count++;
getTriangleRay(node->nodes[i], frustum, device, vPickRayOrig, vPickRayDir);
}
}
// If there were any children nodes then dont continue
if(count != 0)
{
return false;
}
// Now intersect each triangle in this node
j = 0;
for(i=0; i<node->triangleCount; i++){
j = i * 3;
v0 = D3DXVECTOR3( node->vertexArray[j].x, node->vertexArray[j].y, node->vertexArray[j].z);
j++;
v1 = D3DXVECTOR3( node->vertexArray[j].x, node->vertexArray[j].y, node->vertexArray[j].z);
j++;
v2 = D3DXVECTOR3( node->vertexArray[j].x, node->vertexArray[j].y, node->vertexArray[j].z);
result = IntersectTriangle( vPickRayOrig, vPickRayDir, v0, v1, v2, &fDist, &fBary1, &fBary2);
if(result == true){
// intersection = true, so get a aproximate center of the triangle on the world
p1 = (v0.x + v0.x + v0.x)/3;
p2 = (v0.y + v1.y + v2.y)/3;
p3 = (v0.z + v1.z + v2.z)/3;
m_mousepos = D3DXVECTOR3(p1, p2, p3);
return true;
}
}
}
bool QuadTreeClass::IntersectTriangle( const D3DXVECTOR3& orig, const D3DXVECTOR3& dir,D3DXVECTOR3& v0, D3DXVECTOR3& v1, D3DXVECTOR3& v2, FLOAT* t, FLOAT* u, FLOAT* v ){
// Find vectors for two edges sharing vert0
D3DXVECTOR3 edge1 = v1 - v0;
D3DXVECTOR3 edge2 = v2 - v0;
// Begin calculating determinant - also used to calculate U parameter
D3DXVECTOR3 pvec;
D3DXVec3Cross( &pvec, &dir, &edge2 );
// If determinant is near zero, ray lies in plane of triangle
FLOAT det = D3DXVec3Dot( &edge1, &pvec );
D3DXVECTOR3 tvec;
if( det > 0 )
{
tvec = orig - v0;
}
else
{
tvec = v0 - orig;
det = -det;
}
if( det < 0.0001f )
return FALSE;
// Calculate U parameter and test bounds
*u = D3DXVec3Dot( &tvec, &pvec );
if( *u < 0.0f || *u > det )
return FALSE;
// Prepare to test V parameter
D3DXVECTOR3 qvec;
D3DXVec3Cross( &qvec, &tvec, &edge1 );
// Calculate V parameter and test bounds
*v = D3DXVec3Dot( &dir, &qvec );
if( *v < 0.0f || *u + *v > det )
return FALSE;
// Calculate t, scale parameters, ray intersects triangle
*t = D3DXVec3Dot( &edge2, &qvec );
FLOAT fInvDet = 1.0f / det;
*t *= fInvDet;
*u *= fInvDet;
*v *= fInvDet;
return TRUE;
}
Please is this code right? If it is then my problem must be related to the quadtree.
Thanks!
Iterating over all visible triangle to find the intersection is very expensive. Additional the cost will rise if your heightmap gets finer.
For my heightmap I use a different approach:
I do a step-by-step search regarding the height on the clickray starting at the origin. At every step the current position is moved along the ray and tested against the height of the heightmap (therefore you need a heightfunction). If the current position is below the heightmap, the last intervall is searched again by an additional iteration to find a finer position. This works as long as your heightmap hasn't a too high frequency in the heightvalues regarding to the stepsize (otherwise you could jump over a peak).

c++ graphical programming

I'm new to c++ 3D, so I may just be missing something obvious, but how do I convert from 3D to 2D and (for a given z location) from 2D to 3D?
You map 3D to 2D via projection. You map 2D to 3D by inserting the appropriate value in the Z element of the vector.
It is a matter of casting a ray from the screen onto a plane which is parallel to x-y and is at the required z location. You then need to find out where on the plane the ray is colliding.
Here's one example, considering that screen_x and screen_y ranges from [0, 1], where 0 is the left-most or top-most coordinate and 1 is right-most or bottom-most, respectively:
Vector3 point_of_contact(-1.0f, -1.0f, -1.0f);
Matrix4 view_matrix = camera->getViewMatrix();
Matrix4 proj_matrix = camera->getProjectionMatrix();
Matrix4 inv_view_proj_matrix = (proj_matrix * view_matrix).inverse();
float nx = (2.0f * screen_x) - 1.0f;
float ny = 1.0f - (2.0f * screen_y);
Vector3 near_point(nx, ny, -1.0f);
Vector3 mid_point(nx, ny, 0.0f);
// Get ray origin and ray target on near plane in world space
Vector3 ray_origin, ray_target;
ray_origin = inv_view_proj_matrix * near_point;
ray_target = inv_view_proj_matrix * mid_point;
Vector3 ray_direction = ray_target - ray_origin;
ray_direction.normalise();
// Check for collision with the plane
Vector3 plane_normal(0.0f, 0.0f, 1.0f);
float denominator = plane_normal.dotProduct(ray_direction);
if (fabs(denom) >= std::numeric_limits<float>::epsilon())
{
float num = plane_normal.dotProduct(ray.getOrigin()) + Vector3(0, 0, z_pos);
float distance = -(num/denom);
if (distance > 0)
{
point_of_contact = ray_origin + (ray_direction * distance);
}
}
return point_of_contact
Disclaimer Notice: This solution was taken from bits and pieces of Ogre3D graphics library.
The simplest way is to do a divide by z. Therefore ...
screenX = projectionX / projectionZ;
screenY = projectionY / projectionZ;
That does perspective projection based on distance. Thing is it is often better to use homgeneous coordinates as this simplifies matrix transformation (everything becomes a multiply). Equally this is what D3D and OpenGL use. Understanding how to use non-homogeneous coordinates (ie an (x,y,z) coordinate triple) will be very helpful for things like shader optimisations however.
One lame solution:
^ y
|
|
| /z
| /
+/--------->x
Angle is the angle between the Ox and Oz axes (
#include <cmath>
typedef struct {
double x,y,z;
} Point3D;
typedef struct {
double x,y;
} Point2D
const double angle = M_PI/4; //can be changed
Point2D* projection(Point3D& point) {
Point2D* p = new Point2D();
p->x = point.x + point.z * sin(angle);
p->y = point.y + point.z * cos(angle);
return p;
}
However there are lots of tutorials on this on the net... Have you googled for it?