I'm trying to write a program for skeletal animation in DirectX 9, I have used LoadMeshFromHierarchy function to load an animated mesh...now I would like to bypass the animController so that I can dictate the animation by reading keyframes from the animated mesh file(ex. tiny.x) and looping through those keys at will.
Here is what I have so far...at this point I have already parsed the .x file successfully and stored each animation, and animationkey for the sole animation set within a class (Anim). When I run this update function the animated mesh is disfigured, i can't figure out why...I assume it is the process by which I update the transformation matrix for each frame...here is my code:
void cAnimationCollection::Update(DWORD AnimSetIndex, DWORD time)
{
D3DXFRAME_EXTENDED *currentFrame = (D3DXFRAME_EXTENDED*)m_entity->m_frameRoot;
cAnimationSet *AnimSet = m_AnimationSets;
assert(AnimSetIndex <= index);
while(AnimSet != NULL)
{
if(AnimSet->m_index == AnimSetIndex)
{
cAnimation *Anim = AnimSet->m_Animations;
while(Anim != NULL)
{
D3DXMatrixIdentity(&Anim->m_Frame->TransformationMatrix);
if(Anim->m_NumScaleKeys && Anim->m_ScaleKeys)
{
DWORD ScaleKey=0, ScaleKey2=0;
for(DWORD i = 0; i < Anim->m_NumScaleKeys; i++)
{
if(time >= Anim->m_ScaleKeys[i].m_Time)
ScaleKey = i;
}
ScaleKey2 = (ScaleKey>=(Anim->m_NumScaleKeys-1))?ScaleKey:ScaleKey+1;
float TimeDiff = Anim->m_ScaleKeys[ScaleKey2].m_Time - Anim->m_ScaleKeys[ScaleKey].m_Time;
if(!TimeDiff)
TimeDiff = 1;
float Scalar = ((float)time - Anim->m_ScaleKeys[ScaleKey].m_Time) / (float)TimeDiff;
D3DXVECTOR3 vecScale = Anim->m_ScaleKeys[ScaleKey2].m_VecKey - Anim->m_ScaleKeys[ScaleKey].m_VecKey;
vecScale *= Scalar;
vecScale += Anim->m_ScaleKeys[ScaleKey].m_VecKey;
D3DXMATRIX matScale;
D3DXMatrixScaling(&matScale, vecScale.x, vecScale.y, vecScale.z);
Anim->m_Frame->TransformationMatrix *= matScale;
}
if(Anim->m_NumRotationKeys && Anim->m_RotationKeys)
{
DWORD RotKey=0, RotKey2=0;
for(DWORD i = 0; i < Anim->m_NumRotationKeys; i++)
{
if(time >= Anim->m_RotationKeys[i].m_Time)
RotKey = i;
}
RotKey2 = (RotKey>=(Anim->m_NumRotationKeys-1))?RotKey:RotKey+1;
float TimeDiff = Anim->m_RotationKeys[RotKey2].m_Time - Anim->m_RotationKeys[RotKey].m_Time;
if(!TimeDiff)
TimeDiff = 1;
float Scalar = ((float)time - Anim->m_RotationKeys[RotKey].m_Time) / (float)TimeDiff;
D3DXQUATERNION quatRotation;
D3DXQuaternionSlerp(&quatRotation,
&Anim->m_RotationKeys[RotKey].m_QuatKey,
&Anim->m_RotationKeys[RotKey2].m_QuatKey,
Scalar);
D3DXMATRIX matRotation;
D3DXMatrixRotationQuaternion(&matRotation, &quatRotation);
Anim->m_Frame->TransformationMatrix *= matRotation;
}
if(Anim->m_NumTranslationKeys && Anim->m_TranslationKeys)
{
DWORD PosKey=0, PosKey2=0;
for(DWORD i = 0; i < Anim->m_NumTranslationKeys; i++)
{
if(time >= Anim->m_TranslationKeys[i].m_Time)
PosKey = i;
}
PosKey2 = (PosKey>=(Anim->m_NumTranslationKeys-1))?PosKey:PosKey+1;
float TimeDiff = Anim->m_TranslationKeys[PosKey2].m_Time - Anim->m_TranslationKeys[PosKey].m_Time;
if(!TimeDiff)
TimeDiff = 1;
float Scalar = ((float)time - Anim->m_TranslationKeys[PosKey].m_Time) / (float)TimeDiff;
D3DXVECTOR3 vecPos = Anim->m_TranslationKeys[PosKey2].m_VecKey - Anim->m_TranslationKeys[PosKey].m_VecKey;
vecPos *= Scalar;
vecPos += Anim->m_TranslationKeys[PosKey].m_VecKey;;
D3DXMATRIX matTranslation;
D3DXMatrixTranslation(&matTranslation, vecPos.x, vecPos.y, vecPos.z);
Anim->m_Frame->TransformationMatrix *= matTranslation;
}
if(Anim->m_NumMatrixKeys && Anim->m_MatrixKeys)
{
DWORD Key1 = 0, Key2 = 0;
for(DWORD i=0;i<Anim->m_NumMatrixKeys;i++)
{
if(time >= Anim->m_MatrixKeys[i].m_Time)
Key1 = i;
}
Key2 = (Key1>=(Anim->m_NumMatrixKeys-1))?Key1:Key1+1;
float TimeDiff = Anim->m_MatrixKeys[Key2].m_Time - Anim->m_MatrixKeys[Key1].m_Time;
if(!TimeDiff)
TimeDiff = 1;
float Scalar = ((float)time - Anim->m_MatrixKeys[Key1].m_Time) / (float)TimeDiff;
D3DXMATRIX matDiff = Anim->m_MatrixKeys[Key2].m_MatKey - Anim->m_MatrixKeys[Key1].m_MatKey;
matDiff *= Scalar;
matDiff += Anim->m_MatrixKeys[Key1].m_MatKey;
Anim->m_Frame->TransformationMatrix *= matDiff;
}
Anim = Anim->m_Next;
}
}
AnimSet = AnimSet->m_Next;
}
m_entity->UpdateFrameMatrices(m_entity->m_frameRoot, 0);
m_entity->UpdateSkinnedMesh(m_entity->m_frameRoot);
if(AnimSet == NULL)
return;
}
Is my method correct? The first thing I do for each frame is reset the transformation matrix to identity, then I calculate an interpolated value for each key(translation, scale, rotation, & matrix) and apply it to the transformation matrix...then I update the frame matrices, and then the skinned mesh.
Any ideas?
Related
I've implemented the Marching Cube algorithm in a DirectX environment (To test and have fun). Upon completion, I noticed that the resulting model looks heavily distorted, as if the indices were off.
I've attempted to extract the indices, but I think the vertices are ordered correctly already, using the lookup tables, examples at http://paulbourke.net/geometry/polygonise/ . The current build uses a 15^3 volume.
Marching cubes iterates over the array as normal:
for (float iX = 0; iX < CellFieldSize.x; iX++){
for (float iY = 0; iY < CellFieldSize.y; iY++){
for (float iZ = 0; iZ < CellFieldSize.z; iZ++){
MarchCubes(XMFLOAT3(iX*StepSize, iY*StepSize, iZ*StepSize), StepSize);
}
}
}
The MarchCube function is called:
void MC::MarchCubes(){
...
int Corner, Vertex, VertexTest, Edge, Triangle, FlagIndex, EdgeFlags;
float Offset;
XMFLOAT3 Color;
float CubeValue[8];
XMFLOAT3 EdgeVertex[12];
XMFLOAT3 EdgeNorm[12];
//Local copy
for (Vertex = 0; Vertex < 8; Vertex++) {
CubeValue[Vertex] = (this->*fSample)(
in_Position.x + VertexOffset[Vertex][0] * Scale,
in_Position.y + VertexOffset[Vertex][1] * Scale,
in_Position.z + VertexOffset[Vertex][2] * Scale
);
}
FlagIndex = 0;
Intersection calculations:
...
//Test vertices for intersection.
for (VertexTest = 0; VertexTest < 8; VertexTest++){
if (CubeValue[VertexTest] <= TargetValue)
FlagIndex |= 1 << VertexTest;
}
//Find which edges are intersected by the surface.
EdgeFlags = CubeEdgeFlags[FlagIndex];
if (EdgeFlags == 0){
return;
}
for (Edge = 0; Edge < 12; Edge++){
if (EdgeFlags & (1 << Edge)) {
Offset = GetOffset(CubeValue[EdgeConnection[Edge][0]], CubeValue[EdgeConnection[Edge][1]], TargetValue); // Get offset function definition. Needed!
EdgeVertex[Edge].x = in_Position.x + VertexOffset[EdgeConnection[Edge][0]][0] + Offset * EdgeDirection[Edge][0] * Scale;
EdgeVertex[Edge].y = in_Position.y + VertexOffset[EdgeConnection[Edge][0]][1] + Offset * EdgeDirection[Edge][1] * Scale;
EdgeVertex[Edge].z = in_Position.z + VertexOffset[EdgeConnection[Edge][0]][2] + Offset * EdgeDirection[Edge][2] * Scale;
GetNormal(EdgeNorm[Edge], EdgeVertex[Edge].x, EdgeVertex[Edge].y, EdgeVertex[Edge].z); //Need normal values
}
}
And the original implementation gets pushed into a holding struct for DirectX.
for (Triangle = 0; Triangle < 5; Triangle++) {
if (TriangleConnectionTable[FlagIndex][3 * Triangle] < 0) break;
for (Corner = 0; Corner < 3; Corner++) {
Vertex = TriangleConnectionTable[FlagIndex][3 * Triangle + Corner];3 * Triangle + Corner]);
GetColor(Color, EdgeVertex[Vertex], EdgeNorm[Vertex]);
Data.VertexData.push_back(XMFLOAT3(EdgeVertex[Vertex].x, EdgeVertex[Vertex].y, EdgeVertex[Vertex].z));
Data.NormalData.push_back(XMFLOAT3(EdgeNorm[Vertex].x, EdgeNorm[Vertex].y, EdgeNorm[Vertex].z));
Data.ColorData.push_back(XMFLOAT4(Color.x, Color.y, Color.z, 1.0f));
}
}
(This is the same ordering as the original GL implementation)
Turns out, I missed a parenthesis showing operator precedence.
EdgeVertex[Edge].x = in_Position.x + (VertexOffset[EdgeConnection[Edge][0]][0] + Offset * EdgeDirection[Edge][0]) * Scale;
EdgeVertex[Edge].y = in_Position.y + (VertexOffset[EdgeConnection[Edge][0]][1] + Offset * EdgeDirection[Edge][1]) * Scale;
EdgeVertex[Edge].z = in_Position.z + (VertexOffset[EdgeConnection[Edge][0]][2] + Offset * EdgeDirection[Edge][2]) * Scale;
Corrected, obtained Visine; resumed fun.
screen shoot:http://1drv.ms/1C9fgyl
pls note that the normal buffer is very strange. I use method in this link: http://www.terathon.com/code/tangent.html
the fabric tangent is very different between left half side and right half side.
I don't know what happen.
I test another sponza scene and put them in other guys who use same method to calc TBN and got same issue.
what's the bug in my algrithom?
bool OBJModel_Loader::BuildTangent(std::vector<OBJModel* >& Objects)
{
for (OBJModel* actor : Objects)
{
PracEngLogf("BuildTangent For Model: %s! \n", actor->Name.c_str());
int cnt = actor->VertexBuffer.size();
PEVector3* tan1 = new PEVector3[cnt * 2];
PEVector3* tan2 = tan1 + cnt;
ZeroMemory(tan1, cnt*sizeof(PEVector3) * 2);
for (size_t i = 0; i < actor->FaceInfos.size(); i+=3)
{
int Idx1 = actor->FaceInfos[i].VertexIdx;
int Idx2 = actor->FaceInfos[i + 1].VertexIdx;
int Idx3 = actor->FaceInfos[i + 2].VertexIdx;
const PEFloat3& v1 = actor->VertexBuffer[Idx1];
const PEFloat3& v2 = actor->VertexBuffer[Idx2];
const PEFloat3& v3 = actor->VertexBuffer[Idx3];
const PEFloat2& w1 = actor->UVs[actor->FaceInfos[i].UVIdx];
const PEFloat2& w2 = actor->UVs[actor->FaceInfos[i+1].UVIdx];
const PEFloat2& w3 = actor->UVs[actor->FaceInfos[i+2].UVIdx];
PEVector3 E1(v2.X - v1.X, v2.Y - v1.Y, v2.Z - v1.Z);
PEVector3 E2(v3.X - v1.X, v3.Y - v1.Y, v3.Z - v1.Z);
PEFloat2 St1 ( w2.X - w1.X, w2.Y - w1.Y );
PEFloat2 St2 ( w3.X - w1.X, w3.Y - w1.Y );
PEVector3 sDir;
PEVector3 tDir;
float r = St1.X*St2.Y - St2.X*St1.Y;
if (fabs(r) < 1e-6f)
{
sDir = PEVector3(1.0f, .0f, .0f);
tDir = PEVector3(.0f, 1.0f, .0f);
}
else
{
r = 1.0f / r;
sDir = PEVector3((St2.Y*E1.x - St1.Y*E2.x)*r, (St2.Y*E1.y - St1.Y*E2.y)*r, (St2.Y*E1.z - St1.Y*E2.z)*r);
tDir = PEVector3((St1.X*E2.x - St2.X*E1.x)*r, (St1.X*E2.y - St2.X*E1.y)*r, (St1.X*E2.z - St2.X*E1.z)*r);
}
tan1[Idx1] += sDir;
tan1[Idx2] += sDir;
tan1[Idx3] += sDir;
tan2[Idx1] += tDir;
tan2[Idx2] += tDir;
tan2[Idx3] += tDir;
}
for (size_t i = 0; i < actor->FaceInfos.size(); i++)
{
int Idx = actor->FaceInfos[i].VertexIdx;
const PEVector3& N = actor->VertexNormal[actor->FaceInfos[i].NormalIdx];
const PEVector3& T = tan1[Idx];
PEVector3 adjTangent = T - N * PEVector3::Dot(N, T);
adjTangent.Normalize();
actor->VertexTangent[Idx] = adjTangent;
actor->VertexTangent[Idx].w = PEVector3::Dot(N.Cross(T), tan2[Idx]) < .0f ? -1.0f : 1.0f;
}
delete[] tan1;
}
return true;
}
This question is a follow from another question I asked here that was answered.
I have the following function:
MotiColor startColor;
MotiColor endColor;
void setup()
{
// Begin strip.
strip.begin();
// Initialize all pixels to 'off'.
strip.show();
Serial1.begin(9600);
startColor = MotiColor(0, 0, 0);
endColor = MotiColor(0, 0, 0);
}
void loop () {
}
int tinkerSetColour(String command)
{
strip.show();
int commaIndex = command.indexOf(',');
int secondCommaIndex = command.indexOf(',', commaIndex+1);
int lastCommaIndex = command.lastIndexOf(',');
String red = command.substring(0, commaIndex);
String grn = command.substring(commaIndex+1, secondCommaIndex);
String blu = command.substring(lastCommaIndex+1);
startColor = MotiColor(red.toInt(), grn.toInt(), blu.toInt());
int16_t redDiff = endColor.getR() - startColor.getR();
int16_t greenDiff = endColor.getG() - startColor.getG();
int16_t blueDiff = endColor.getB() - startColor.getB();
int16_t _delay = 500;
int16_t duration = 3500;
int16_t steps = duration / _delay;
int16_t redValue, greenValue, blueValue;
for (int16_t i = steps; i >= 0; i--) {
redValue = (int16_t)startColor.getR() + (redDiff * i / steps);
greenValue = (int16_t)startColor.getG() + (greenDiff * i / steps);
blueValue = (int16_t)startColor.getB() + (blueDiff * i / steps);
sprintf(rgbString, "%i,%i,%i", redValue, greenValue, blueValue);
Spark.publish("rgb", rgbString);
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(redValue, greenValue, blueValue));
}
delay(_delay);
}
delay(_delay);
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(endColor.getR(), endColor.getG(), endColor.getB()));
}
delay(_delay);
endColor = MotiColor(startColor.getR(), startColor.getG(), startColor.getB());
return 1;
}
I am seeing the published results correctly:
This is from OFF (0,0,0) -> RED (255,0,0) -> GREEN (0,255,0).
It works fine when I publish the results back to a web console via the Spark.publish() event, however the actual Neopixel LED's don't fade from colour to colour as expected. They just change from colour to colour instead of fading nicely between themselves.
I'm just wondering where I'm going wrong or how I can improve my code so that I actually see the fading in real time.
You have to call strip.show() in your for loop, like so:
for (int16_t i = steps; i >= 0; i--) {
redValue = (int16_t)startColor.getR() + (redDiff * i / steps);
greenValue = (int16_t)startColor.getG() + (greenDiff * i / steps);
blueValue = (int16_t)startColor.getB() + (blueDiff * i / steps);
sprintf(rgbString, "%i,%i,%i", redValue, greenValue, blueValue);
Spark.publish("rgb", rgbString);
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(redValue, greenValue, blueValue));
}
// !!! Without this, you'll only see the result the next time you call
// tinkerSetColor() !!!
strip.show();
delay(_delay);
}
To understand what's happening, you can look at the NeoPixel library source. You'll see that strip.setPixelColor() only stores the RGB value in memory (think of it as a drawing buffer, so that you can update the whole strip at once, which makes sense if you look at how the controller chips work). Calling strip.show() causes the routine that will push the values out to each pixel in serial to run.
I am new to 3d programming so here goes. I am trying to simulate a room. I don't have images for the walls loaded but I want to in code simulate the boundaries. How do I accomplish this please?
Below is the code that handles the movement of the camera
bool calcMovement()
{
// return if less then two events have been added.
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
//calcIntersect();
double dt = _ga_t0->getTime()-_ga_t1->getTime();
if (dt<0.0f)
{
OSG_INFO << "warning dt = "<<dt<< std::endl;
dt = 0.0;
}
double accelerationFactor = _height*10.0;
switch(_speedMode)
{
case(USE_MOUSE_Y_FOR_SPEED):
{
double dy = _ga_t0->getYnormalized();
_velocity = _height*dy;
break;
}
case(USE_MOUSE_BUTTONS_FOR_SPEED):
{
unsigned int buttonMask = _ga_t1->getButtonMask();
//add cases here for finding which key was pressed.
if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON || wPressed)
{
// pan model.
_velocity += dt*accelerationFactor;
}
else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))
{
_velocity = 0.0;
}
else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON || sPressed)
{
_velocity -= dt*accelerationFactor;
}
break;
}
}
osg::CoordinateFrame cf=getCoordinateFrame(_eye);
osg::Matrixd rotation_matrix;
rotation_matrix.makeRotate(_rotation);
osg::Vec3d up = osg::Vec3d(0.0,1.0,0.0) * rotation_matrix;
osg::Vec3d lv = osg::Vec3d(0.0,0.0,-1.0) * rotation_matrix;
osg::Vec3d sv = osg::Vec3d(1.0,0.0,0.0) * rotation_matrix;
// rotate the camera.
double dx = _ga_t0->getXnormalized();
double yaw = -inDegrees(dx*50.0*dt);
#ifdef KEYBOARD_PITCH
double pitch_delta = 0.5;
if (_pitchUpKeyPressed) _pitch += pitch_delta*dt;
if (_pitchDownKeyPressed) _pitch -= pitch_delta*dt;
#endif
#if defined(ABOSULTE_PITCH)
// absolute pitch
double dy = _ga_t0->getYnormalized();
_pitch = -dy*0.5;
#elif defined(INCREMENTAL_PITCH)
// incremental pitch
double dy = _ga_t0->getYnormalized();
_pitch += dy*dt;
#endif
osg::Quat yaw_rotation;
yaw_rotation.makeRotate(yaw,up);
_rotation *= yaw_rotation;
rotation_matrix.makeRotate(_rotation);
sv = osg::Vec3d(1.0,0.0,0.0) * rotation_matrix;
wPressed = false;
sPressed = false;
// movement is big enough the move the eye point along the look vector.
if (fabs(_velocity*dt)>1e-8)
{
double distanceToMove = _velocity*dt;
double signedBuffer;
if (distanceToMove>=0.0) signedBuffer=_buffer;
else signedBuffer=-_buffer;
// check to see if any obstruction in front.
osg::Vec3d ip, np;
if (intersect(_eye,_eye+lv*(signedBuffer+distanceToMove), ip, np))
{
if (distanceToMove>=0.0)
{
distanceToMove = (ip-_eye).length()-_buffer;
}
else
{
distanceToMove = _buffer-(ip-_eye).length();
}
_velocity = 0.0;
}
// check to see if forward point is correct height above terrain.
osg::Vec3d fp = _eye + lv*distanceToMove;
osg::Vec3d lfp = fp - up*(_height*5.0);
if (intersect(fp, lfp, ip, np))
{
if (up*np>0.0) up = np;
else up = -np;
_eye = ip+up*_height;
lv = up^sv;
computePosition(_eye,_eye+lv,up);
return true;
}
// no hit on the terrain found therefore resort to a fall under
// under the influence of gravity.
osg::Vec3d dp = lfp;
dp -= getUpVector(cf)* (2.0*_modelScale);
if (intersect(lfp, dp, ip, np))
{
if (up*np>0.0) up = np;
else up = -np;
_eye = ip+up*_height;
lv = up^sv;
computePosition(_eye,_eye+lv,up);
return true;
}
// no collision with terrain has been found therefore track horizontally.
lv *= (_velocity*dt);
_eye += lv;
}
return true;
}
I have written some code to preform 3D picking that for some reason dosn't work entirely correct! (Im using LWJGL just so you know.)
This is how the code looks like:
if(Mouse.getEventButton() == 1) {
if (!Mouse.getEventButtonState()) {
Camera.get().generateViewMatrix();
float screenSpaceX = ((Mouse.getX()/800f/2f)-1.0f)*Camera.get().getAspectRatio();
float screenSpaceY = 1.0f-(2*((600-Mouse.getY())/600f));
float displacementRate = (float)Math.tan(Camera.get().getFovy()/2);
screenSpaceX *= displacementRate;
screenSpaceY *= displacementRate;
Vector4f cameraSpaceNear = new Vector4f((float) (screenSpaceX * Camera.get().getNear()), (float) (screenSpaceY * Camera.get().getNear()), (float) (-Camera.get().getNear()), 1);
Vector4f cameraSpaceFar = new Vector4f((float) (screenSpaceX * Camera.get().getFar()), (float) (screenSpaceY * Camera.get().getFar()), (float) (-Camera.get().getFar()), 1);
Matrix4f tmpView = new Matrix4f();
Camera.get().getViewMatrix().transpose(tmpView);
Matrix4f invertedViewMatrix = (Matrix4f)tmpView.invert();
Vector4f worldSpaceNear = new Vector4f();
Matrix4f.transform(invertedViewMatrix, cameraSpaceNear, worldSpaceNear);
Vector4f worldSpaceFar = new Vector4f();
Matrix4f.transform(invertedViewMatrix, cameraSpaceFar, worldSpaceFar);
Vector3f rayPosition = new Vector3f(worldSpaceNear.x, worldSpaceNear.y, worldSpaceNear.z);
Vector3f rayDirection = new Vector3f(worldSpaceFar.x - worldSpaceNear.x, worldSpaceFar.y - worldSpaceNear.y, worldSpaceFar.z - worldSpaceNear.z);
rayDirection.normalise();
Ray clickRay = new Ray(rayPosition, rayDirection);
Vector tMin = new Vector(), tMax = new Vector(), tempPoint;
float largestEnteringValue, smallestExitingValue, temp, closestEnteringValue = Camera.get().getFar()+0.1f;
Drawable closestDrawableHit = null;
for(Drawable d : this.worldModel.getDrawableThings()) {
// Calcualte AABB for each object... needs to be moved later...
firstVertex = true;
for(Surface surface : d.getSurfaces()) {
for(Vertex v : surface.getVertices()) {
worldPosition.x = (v.x+d.getPosition().x)*d.getScale().x;
worldPosition.y = (v.y+d.getPosition().y)*d.getScale().y;
worldPosition.z = (v.z+d.getPosition().z)*d.getScale().z;
worldPosition = worldPosition.rotate(d.getRotation());
if (firstVertex) {
maxX = worldPosition.x; maxY = worldPosition.y; maxZ = worldPosition.z;
minX = worldPosition.x; minY = worldPosition.y; minZ = worldPosition.z;
firstVertex = false;
} else {
if (worldPosition.x > maxX) {
maxX = worldPosition.x;
}
if (worldPosition.x < minX) {
minX = worldPosition.x;
}
if (worldPosition.y > maxY) {
maxY = worldPosition.y;
}
if (worldPosition.y < minY) {
minY = worldPosition.y;
}
if (worldPosition.z > maxZ) {
maxZ = worldPosition.z;
}
if (worldPosition.z < minZ) {
minZ = worldPosition.z;
}
}
}
}
// ray/slabs intersection test...
// clickRay.getOrigin().x + clickRay.getDirection().x * f = minX
// clickRay.getOrigin().x - minX = -clickRay.getDirection().x * f
// clickRay.getOrigin().x/-clickRay.getDirection().x - minX/-clickRay.getDirection().x = f
// -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x = f
largestEnteringValue = -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x;
temp = -clickRay.getOrigin().y/clickRay.getDirection().y + minY/clickRay.getDirection().y;
if(largestEnteringValue < temp) {
largestEnteringValue = temp;
}
temp = -clickRay.getOrigin().z/clickRay.getDirection().z + minZ/clickRay.getDirection().z;
if(largestEnteringValue < temp) {
largestEnteringValue = temp;
}
smallestExitingValue = -clickRay.getOrigin().x/clickRay.getDirection().x + maxX/clickRay.getDirection().x;
temp = -clickRay.getOrigin().y/clickRay.getDirection().y + maxY/clickRay.getDirection().y;
if(smallestExitingValue > temp) {
smallestExitingValue = temp;
}
temp = -clickRay.getOrigin().z/clickRay.getDirection().z + maxZ/clickRay.getDirection().z;
if(smallestExitingValue < temp) {
smallestExitingValue = temp;
}
if(largestEnteringValue > smallestExitingValue) {
//System.out.println("Miss!");
} else {
if (largestEnteringValue < closestEnteringValue) {
closestEnteringValue = largestEnteringValue;
closestDrawableHit = d;
}
}
}
if(closestDrawableHit != null) {
System.out.println("Hit at: (" + clickRay.setDistance(closestEnteringValue).x + ", " + clickRay.getCurrentPosition().y + ", " + clickRay.getCurrentPosition().z);
this.worldModel.removeDrawableThing(closestDrawableHit);
}
}
}
I just don't understand what's wrong, the ray are shooting and i do hit stuff that gets removed but the result of the ray are verry strange it sometimes removes the thing im clicking at, sometimes it removes things thats not even close to what im clicking at, and sometimes it removes nothing at all.
Edit:
Okay so i have continued searching for errors and by debugging the ray (by painting smal dots where it travles) i can now se that there is something oviously wrong with the ray that im sending out... it has its origin near the world center and always shots to the same position no matter where i direct my camera...
My initial toughts is that there might be some error in the way i calculate my viewMatrix (since it's not possible to get the viewmatrix from the glulookat method in lwjgl; I have to build it my self and I guess thats where the problem is at)...
Edit2:
This is how i calculate it currently:
private double[][] viewMatrixDouble = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,1}};
public Vector getCameraDirectionVector() {
Vector actualEye = this.getActualEyePosition();
return new Vector(lookAt.x-actualEye.x, lookAt.y-actualEye.y, lookAt.z-actualEye.z);
}
public Vector getActualEyePosition() {
return eye.rotate(this.getRotation());
}
public void generateViewMatrix() {
Vector cameraDirectionVector = getCameraDirectionVector().normalize();
Vector side = Vector.cross(cameraDirectionVector, this.upVector).normalize();
Vector up = Vector.cross(side, cameraDirectionVector);
viewMatrixDouble[0][0] = side.x; viewMatrixDouble[0][1] = up.x; viewMatrixDouble[0][2] = -cameraDirectionVector.x;
viewMatrixDouble[1][0] = side.y; viewMatrixDouble[1][1] = up.y; viewMatrixDouble[1][2] = -cameraDirectionVector.y;
viewMatrixDouble[2][0] = side.z; viewMatrixDouble[2][1] = up.z; viewMatrixDouble[2][2] = -cameraDirectionVector.z;
/*
Vector actualEyePosition = this.getActualEyePosition();
Vector zaxis = new Vector(this.lookAt.x - actualEyePosition.x, this.lookAt.y - actualEyePosition.y, this.lookAt.z - actualEyePosition.z).normalize();
Vector xaxis = Vector.cross(upVector, zaxis).normalize();
Vector yaxis = Vector.cross(zaxis, xaxis);
viewMatrixDouble[0][0] = xaxis.x; viewMatrixDouble[0][1] = yaxis.x; viewMatrixDouble[0][2] = zaxis.x;
viewMatrixDouble[1][0] = xaxis.y; viewMatrixDouble[1][1] = yaxis.y; viewMatrixDouble[1][2] = zaxis.y;
viewMatrixDouble[2][0] = xaxis.z; viewMatrixDouble[2][1] = yaxis.z; viewMatrixDouble[2][2] = zaxis.z;
viewMatrixDouble[3][0] = -Vector.dot(xaxis, actualEyePosition); viewMatrixDouble[3][1] =-Vector.dot(yaxis, actualEyePosition); viewMatrixDouble[3][2] = -Vector.dot(zaxis, actualEyePosition);
*/
viewMatrix = new Matrix4f();
viewMatrix.load(getViewMatrixAsFloatBuffer());
}
Would be verry greatfull if anyone could verify if this is wrong or right, and if it's wrong; supply me with the right way of doing it...
I have read alot of threads and documentations about this but i can't seam to wrapp my head around it...
I just don't understand what's wrong, the ray are shooting and i do hit stuff that gets removed but things are not disappearing where i press on the screen.
OpenGL is not a scene graph, it's a drawing library. So after removing something from your internal representation you must redraw the scene. And your code is missing some call to a function that triggers a redraw.
Okay so i finaly solved it with the help from the guys at gamedev and a friend, here is a link to the answer where i have posted the code!