void WorldRenderer::UpdateWaterBoxes( WaterQuad* quad ) { // Create Boxes if ( zShowWaterBoxes ) { auto i = zWaterBoxes.find(quad); if ( i != zWaterBoxes.end() ) { // Calculate Positions for( unsigned int x=0; x<4; ++x ) { Vector3 position; position = quad->GetPosition(x); // Terrain Height Minimum try { float terrainHeight = zWorld->CalcHeightAtWorldPos(position.GetXZ()); if ( position.y < terrainHeight ) position.y = terrainHeight; } catch(...) { } i->second.zCubes[x]->SetPosition(position); } } else { // Calculate Positions Vector3 positions[4]; for( unsigned int x=0; x<4; ++x ) { positions[x] = quad->GetPosition(x); // Terrain Height Minimum try { float terrainHeight = zWorld->CalcHeightAtWorldPos(positions[x].GetXZ()); if ( positions[x].y < terrainHeight ) positions[x].y = terrainHeight; } catch(...) { } } zWaterBoxes[quad].zCubes[0] = zGraphics->CreateMesh("Media/Models/Cube_1.obj", positions[0]); zWaterBoxes[quad].zCubes[1] = zGraphics->CreateMesh("Media/Models/Cube_2.obj", positions[1]); zWaterBoxes[quad].zCubes[2] = zGraphics->CreateMesh("Media/Models/Cube_3.obj", positions[2]); zWaterBoxes[quad].zCubes[3] = zGraphics->CreateMesh("Media/Models/Cube_4.obj", positions[3]); for( unsigned int x=0; x<4; ++x ) { zWaterBoxes[quad].zCubes[x]->SetScale(1.0f/20.0f); } } } }
Actor* ProjectileArrowBehavior::RayVsMeshCollision( const Actor* actor, const Vector3& rayOrigin, float& range, const std::set<Actor*>& actors ) { if( !actor || !actor->CanCollide() ) return NULL; float rangeWithin = 1.0f + range; PhysicsCollisionData data; ProjectileActor* projActor = dynamic_cast<ProjectileActor*>(this->zActor); if( !projActor ) return Behavior::RayVsMeshCollision(actor, rayOrigin, range, actors); Actor* collide = NULL; Actor* owner = NULL; Vector3 pos = actor->GetPosition(); Vector3 dir = actor->GetDir(); owner = projActor->GetOwner(); if(!owner) return NULL; auto it_end = actors.end(); for (auto it = actors.begin(); it != it_end; it++) { if( *it == this->zActor ) continue; if( *it == owner ) continue; if( !(*it)->CanCollide() ) continue; float distance = ( pos.GetXZ() - (*it)->GetPosition().GetXZ() ).GetLength(); if( distance > rangeWithin ) continue; PhysicsObject* targetObject = (*it)->GetPhysicsObject(); data = GetPhysics()->GetCollisionRayMesh(rayOrigin, dir, targetObject); if(data.collision && data.distance < range) { range = data.distance; collide = (*it); } } return collide; }
bool ProjectileArrowBehavior::Update( float dt ) { if(!zMoving) return true; Vector3 newPos; Vector3 newDir; // Update linear position. newPos = this->zActor->GetPosition(); zVelocity.Normalize(); zVelocity *= zSpeed; newPos += (zVelocity * dt); newDir = zVelocity; newDir.Normalize(); //Rotate Mesh Vector3 ProjectileStartDirection = Vector3(0,0,-1); Vector3 ProjectileMoveDirection = newDir; ProjectileStartDirection.Normalize(); Vector3 around = ProjectileStartDirection.GetCrossProduct(ProjectileMoveDirection); float angle = acos(ProjectileStartDirection.GetDotProduct(ProjectileMoveDirection)); //Set Values this->zActor->SetPosition(newPos, false); this->zActor->SetRotation(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); this->zActor->SetRotation(around, angle); this->zActor->SetDir(newDir); /**Check If the arrow is outside the world.**/ if( !this->zWorld->IsInside(newPos.GetXZ()) ) { Stop(); this->zActor->SetPosition(newPos); return true; } //**Check if the projectile has hit the ground** float yValue = std::numeric_limits<float>::lowest(); try { yValue = this->zWorld->CalcHeightAtWorldPos(newPos.GetXZ()); } catch(...) { Stop(); this->zActor->SetPosition(newPos); return true; } // If true, stop the projectile and return. float middle = zLength * 0.5f; float yTip = newPos.y - middle; if(yTip <= yValue ) { middle += yValue; newPos.y = middle; this->Stop(); this->zActor->SetPosition(newPos); return true; } //**Update Velocity for next update** // Update linear velocity from the acceleration. this->zVelocity += (GRAVITY * dt); // Impose drag. this->zVelocity *= pow(zDamping, dt); //Update-Notify Position this->zActor->SetPosition(newPos); /***Check collisions***/ //Check if the arrow has hit a dynamic actor Actor* collide = RayVsMeshDynamicActorCollision(zLength, newPos); if(collide) { this->Stop(); ProjectileArrowCollide PAC; PAC.zActor = collide; NotifyObservers(&PAC); if( BioActor* bioActor = dynamic_cast<BioActor*>(collide) ) { if( bioActor->IsAlive() ) { ProjectileActor* projActor = dynamic_cast<ProjectileActor*>(this->zActor); bioActor->TakeDamage( projActor->GetDamage(), projActor->GetOwner() ); } } this->zHitTarget = collide; return true; } //Check if the arrow has hit a static actor collide = RayVsMeshStaticActorCollision(zLength, newPos); if(collide) { this->Stop(); ProjectileArrowCollide PAC; PAC.zActor = collide; NotifyObservers(&PAC); this->zHitTarget = collide; return true; } return false; }
bool WorldRenderer::Update() { // Update Terrain Routine UpdateTerrain(); // Cam Pos Vector3 camPos = zGraphics->GetCamera()->GetPosition(); // Don't update grass if we don't have a world if ( zWorld ) { // Check if we should render grass zGraphics->SetGrassFilePath("Media/Grass.png"); if ( zGraphics->GetRenderGrassFlag() ) { if ( (zLastGrassUpdatePos - camPos.GetXZ()).GetLength() >= zGrassUpdateDistance ) { std::map<Vector2UINT, int> grassSectors; // Remove Current Grass Sectors for( auto i = zGrass.cbegin(); i != zGrass.cend(); ++i ) { grassSectors[i->first]--; } // Insert New Sectors std::set<Vector2UINT> newSectorsSet; zWorld->GetSectorsInCicle(camPos.GetXZ(), zGrassFarDistance, newSectorsSet); for( auto i = newSectorsSet.cbegin(); i != newSectorsSet.cend(); ++i ) { grassSectors[*i]++; } // Update Sector Grasses for( auto i = grassSectors.cbegin(); i != grassSectors.cend(); ++i ) { if ( i->second < 0 ) { auto grassIt = zGrass.find(i->first); if ( grassIt != zGrass.cend() ) { if ( grassIt->second ) { zGraphics->DeleteBillboardCollection(grassIt->second); } zGrass.erase(grassIt); } } else if ( i->second > 0 ) { GenerateGrass(i->first); } } zLastGrassUpdatePos = camPos.GetXZ(); } } } // Check Distance if ( (zLastEntUpdatePos - camPos).GetLength() > 10.0f ) { // Update Existing LOD for( auto i = zEntities.cbegin(); i != zEntities.cend(); ++i ) { zEntsToUpdate.insert(i->first); } // Scan New Entities if ( zWorld ) { zWorld->GetEntitiesInCircle(camPos.GetXZ(), zGraphics->GetEngineParameters().FarClip, zEntsToUpdate); } // Update Position zLastEntUpdatePos = camPos; } // Update a between 10% and a minimum of 25 unsigned int x = zEntsToUpdate.size() / 10; if ( x < 25 ) x = 25; if ( x > 100 ) x = 100; auto i = zEntsToUpdate.begin(); while( i != zEntsToUpdate.end() ) { SetEntityGraphics(*i); i = zEntsToUpdate.erase(i); if ( !x || !--x ) break; } // Check if there is more to be updated return ( zEntsToUpdate.size() > 0 || zUpdatesRequired.size() > 0 ); }