/*! \param screen_position screen position \param position_ position \param direction_ direction */ void Storm3D_Scene::GetEyeVectors(const VC2I &screen_position, Vector &position_, Vector &direction_) { static const float NEAR_Z = 2.f; D3DXMATRIX pProjection; D3DXMATRIX pView; VC3 camera_up = camera.GetUpVec(); VC3 camera_position = camera.GetPosition(); VC3 camera_target = camera.GetTarget(); D3DXMatrixLookAtLH(pView, camera_position, camera_target, camera_up); //RECT windowSize = { 0 }; //GetClientRect(Storm3D2->window_handle, &windowSize); igios_unimplemented(); Storm3D_SurfaceInfo ss = Storm3D2->GetScreenSize(); float aspect=(float) ss.width / (float) ss.height; float fov = camera.GetFieldOfView(); float vis_range = camera.GetVisibilityRange(); VC3 pV; D3DXMatrixPerspectiveFovLH(pProjection,fov,aspect,1.0f,vis_range); pV.x = 1.0f; pV.y = 1.0f; pV.z = 1.0f; //pV.x = ( ( ( 2.0f * (float)screen_position.x ) / windowSize.right ) - 1 ) / pProjection._11; //pV.y = -( ( ( 2.0f * (float)screen_position.y ) / windowSize.bottom ) - 1 ) / pProjection._22; //pV.z = 1.0f; D3DXMATRIX m; D3DXMatrixInverse(m, NULL, pView); VC3 vPickRayDir; VC3 vPickRayOrig; vPickRayDir.x = pV.x*m._11 + pV.y*m._21 + pV.z*m._31; vPickRayDir.y = pV.x*m._12 + pV.y*m._22 + pV.z*m._32; vPickRayDir.z = pV.x*m._13 + pV.y*m._23 + pV.z*m._33; vPickRayDir = vPickRayDir.GetNormalized(); vPickRayOrig.x = m._41; vPickRayOrig.y = m._42; vPickRayOrig.z = m._43; vPickRayOrig+=vPickRayDir*NEAR_Z; direction_.x = vPickRayDir.x; direction_.y = vPickRayDir.y; direction_.z = vPickRayDir.z; position_.x = vPickRayOrig.x; position_.y = vPickRayOrig.y; position_.z = vPickRayOrig.z; }
void GravityPointParticleForce::calcForce(Vector& force, const Vector& pos, const Vector& vel) { VC3 diff = pos - m_point; VC3 diffNorm = diff.GetNormalized(); float diffLenSq = diff.GetSquareLength(); if (fabsf(diffLenSq) < 0.01f) { force.x = 0.0f; force.y = 0.0f; force.z = 0.0f; } else { // realistic gravity (bad) //force = -diffNorm * 0.001f * m_gravity / diffLenSq; // unrealisic gravity (better) float diffLen = sqrtf(diffLenSq); force = -diffNorm * 0.001f * m_gravity / diffLen; } }
bool LineAreaChecker::isPointInsideLineArea(const VC3 &point, const VC3 &lineStart, const VC3 &lineEnd, float lineWidth) { VC3 projPos = lineEnd - lineStart; float projPosLenSq = projPos.GetSquareLength(); VC3 projPosNorm = VC3(0,0,0); if (projPosLenSq > 0.00001f) { projPosNorm = projPos.GetNormalized(); } VC3 chkpos = point - lineStart; float chkposLen = chkpos.GetLength(); VC3 hitAndUnitDiff = chkpos - projPos; float hitAndUnitDiffLenSq = hitAndUnitDiff.GetSquareLength(); float lineRadiusSq = (float)(lineWidth * lineWidth); if (hitAndUnitDiffLenSq < lineRadiusSq) { return true; } if (chkposLen * chkposLen < projPosLenSq) { VC3 pipedPos = projPosNorm * chkposLen; VC3 posdiff = chkpos - pipedPos; if (posdiff.GetSquareLength() < lineRadiusSq) { return true; } } return false; }
// return true if position ok and decal should be added // false, if position NOT ok and decal should NOT be added bool DecalPositionCalculator::calculateDecalPosition( game::GameScene *gameScene, const VC3 &origin, const VC3 &velocity, DECAL_POSITIONING positioning, int positionRandom, VC3 *resultPosition, QUAT *resultRotation) { assert(positioning != DecalPositionCalculator::DECAL_POSITIONING_INVALID); game::GameMap *gameMap = gameScene->getGameMap(); bool hitWall = false; *resultPosition = origin; *resultRotation = QUAT((-3.1415926f / 2.0f),0,0); // if velocity positioning... if (positioning == DecalPositionCalculator::DECAL_POSITIONING_VELOCITY) { VC3 velocityRandomized; if (positionRandom > 0) { velocityRandomized = velocity * GAME_TICKS_PER_SECOND; // TEMP //char buf[64]; //sprintf(buf, "%f,%f,%f", velocity.x, velocity.y, velocity.z); //Logger::getInstance()->error(buf); // TODO: add positionRandom to velocity _angle_... // (or maybe just do a quick hack and add it to xz-coordinates?) velocityRandomized.x += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f; velocityRandomized.z += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f; // add to y too? maybe should add downward only? // NOTE: biased downward velocityRandomized.y += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f; velocityRandomized.y -= float(positionRandom) / 100.0f * 0.5f; } else { velocityRandomized = velocity; } velocityRandomized *= 2.0f; IStorm3D_Scene *scene = gameScene->getStormScene(); VC3 dir = velocityRandomized.GetNormalized(); VC3 rayOrigin = origin; float rayLen = velocityRandomized.GetLength(); Storm3D_CollisionInfo sceneColl; sceneColl.includeTerrainObjects = false; scene->RayTrace(rayOrigin, dir, rayLen, sceneColl, true); /* if (sceneColl.hit) { VC3 hitNormal = sceneColl.plane_normal; // make a "wall" hit if normal-y is not nearly 1 //if (fabs(hitNormal.y) < 0.8f) { hitWall = true; VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f); x.Normalize(); x -= hitNormal * x.GetDotWith(hitNormal); VC3 y = -x.GetCrossWith(hitNormal); assert(fabsf(x.GetDotWith(y)) < 0.0001f); assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f); MAT tm; tm.Set(0, x.x); tm.Set(1, x.y); tm.Set(2, x.z); tm.Set(4, y.x); tm.Set(5, y.y); tm.Set(6, y.z); tm.Set(8, hitNormal.x); tm.Set(9, hitNormal.y); tm.Set(10, hitNormal.z); *resultRotation = tm.GetRotation(); } *resultPosition = sceneColl.position; } else { *resultPosition += velocityRandomized; } */ // New version { VC3 hitNormal(0, 1.f, 0); if(sceneColl.hit) { hitNormal = sceneColl.plane_normal; *resultPosition = sceneColl.position; } else { *resultPosition += velocityRandomized; VC2 p2(resultPosition->x, resultPosition->z); hitNormal = gameScene->getTerrain()->getFaceNormal(p2); } { if(sceneColl.hit) hitWall = true; /* VC3 y = dir; VC3 z = hitNormal; y -= hitNormal * y.GetDotWith(hitNormal); VC3 x = z.GetCrossWith(y); */ VC3 x = dir; x.y = 0.f; x.Normalize(); x -= hitNormal * x.GetDotWith(hitNormal); VC3 y = -x.GetCrossWith(hitNormal); VC3 z = hitNormal; MAT tm; tm.Set(0, x.x); tm.Set(1, x.y); tm.Set(2, x.z); tm.Set(4, y.x); tm.Set(5, y.y); tm.Set(6, y.z); tm.Set(8, z.x); tm.Set(9, z.y); tm.Set(10, z.z); resultRotation->MakeFromAngles(0.f, 0.f, -PI*0.5f); *resultRotation = (*resultRotation) * tm.GetRotation(); /* VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f); x.Normalize(); x -= hitNormal * x.GetDotWith(hitNormal); VC3 y = -x.GetCrossWith(hitNormal); assert(fabsf(x.GetDotWith(y)) < 0.0001f); assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f); MAT tm; tm.Set(0, x.x); tm.Set(1, x.y); tm.Set(2, x.z); tm.Set(4, y.x); tm.Set(5, y.y); tm.Set(6, y.z); tm.Set(8, hitNormal.x); tm.Set(9, hitNormal.y); tm.Set(10, hitNormal.z); *resultRotation = tm.GetRotation(); */ } } // TODO: some kind of terrain raytrace maybe...? // should collide to walls, etc. } // if downward positioning... if (positioning == DecalPositionCalculator::DECAL_POSITIONING_DOWNWARD) { if (positionRandom > 0) { // TODO: add a random xz-offset to result position //*resultPosition += randomizedOffset; resultPosition->x += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f; resultPosition->z += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f; } /* // psd { VC2 p2(resultPosition->x, resultPosition->z); VC3 hitNormal = gameScene->getTerrain()->getFaceNormal(p2); VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f); x.Normalize(); x -= hitNormal * x.GetDotWith(hitNormal); VC3 y = -x.GetCrossWith(hitNormal); assert(fabsf(x.GetDotWith(y)) < 0.0001f); assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f); MAT tm; tm.Set(0, x.x); tm.Set(1, x.y); tm.Set(2, x.z); tm.Set(4, y.x); tm.Set(5, y.y); tm.Set(6, y.z); tm.Set(8, hitNormal.x); tm.Set(9, hitNormal.y); tm.Set(10, hitNormal.z); *resultRotation = tm.GetRotation(); } */ VC3 fooNormal; calculateDecalRotation(gameScene, *resultPosition, *resultRotation, 0.f, fooNormal); } // now check that we're still inside map boundaries if (!gameMap->isWellInScaledBoundaries(resultPosition->x, resultPosition->z)) { // out of map. return false; } // then fix decal height to ground height if (positioning == DecalPositionCalculator::DECAL_POSITIONING_DOWNWARD || positioning == DecalPositionCalculator::DECAL_POSITIONING_VELOCITY) { if (!hitWall) { resultPosition->y = gameMap->getScaledHeightAt(resultPosition->x, resultPosition->z); } } // check that not on top of metal grid area... if (game::MaterialManager::isMaterialUnderPosition(gameMap, *resultPosition, MATERIAL_METAL_GRATE)) { // on top of grid, no decal here. return false; } // TODO: check that not inside a wall, terrainobject, etc. // if so, return false return true; }