User Manual

Download and Open the Simulation

For this project the following Unreal Engine version is needed: at least 4.14.x. In addition the Runtime Mesh Component plugin must be installed.

Java 8 must be installed on the system. It is important that your Path to mysiccom.jar doesn't contain any spaces. An IDE Microsoft Visual Studio 2015 (VS14) is highly recommended.

This simulation has been developed and tested on the following system:

Processor RAM Operating System GPU Add. Requirements:
Intel Core i7-6700K @ 4.00 GHz 64.00GB Windows 10 Enterprise - 64bit NVIDIA GeForce GTX 1080 1x USB-3.0-Port, HTC Vive

Simply double click the project file (.uproject) in the folder, wait for Unreal Engine to open and press "Play" in the top bar of the window.

Ingame Controls


                Use the Mouse to look around. Left Click to open the menu and select with your mouse the desired button. Left click again to chose or close the menu.

                Time of Day control: 
                Toggle FastForward      T
                Increase speed          P
                Decrease speed          O

                Movement:
                Swim Forward:           W       
                Swim Backward:          S       
                Slide Left:             A       
                Slide Right:            D       
                Control Camera:         Mouse      
                Swim Up:                Left Shift 
                Swim Down:              Left Control

                Other:
                Toggle Flashlight       F
                Toggle HUD Icons        I

                3D Radial Menu          Left Click

                


                To look around you simply move your head while equipped with the HTC Vive.

                Movement:
                Swim Forward:           Backside Button of Right Controller      
                Swim Backward:          Backside Button of Left Controller            
                Control Camera:         Use your Head      

                Other:
                Toggle Flashlight       Press Touchpad on Left Controller

                Menu:
                3D Radial Menu          Press Touchpad on Right Controller
                Navigate                Move Finger on Pad
                Choose                  Click on Pad while on Button to choose
                Close                   Click on Pad while in the Center

                

The (VR) Ingame Menu

Menu

For the menu we used icons from other sources. These may be found here.

Complete List of Features


        An immersive lifelike coral reef based on the flora and fauna of a Zanzibar reef
        Created for an Virtual Reality experience 
        Algorithmic birth, growth and decease of corals based on data received from the integrated SICCOM plugin (see paper below)
        Over 40 selfmade models
            4 different kinds of generated corals
            3 different modeled corals
            2 types of algae
                Textured and animated
            10 different types of animals
                including fish, predators, crabs, turtles, stingrays, starfish
                Every model is textured and animated
            Rocks, wrecks, anchor and many more static objects
        Generated corals and algae fight for dominance within the reef
        They also react on parametrical changes such as a change in temperature
        Swarm algorithms simulate different behaviour of fish and predators (domain-driven design [DDD])
            Different states like "Travelling", "Hungry" or "Hunting"
            They can be found either in swarms, small groups or alone
            Sharks hunt in packs, fish try to regroup after a predator attacked
            Fish nibble on corals, making them bleach
        Feature-rich ingame (VR) menu 
            Simulation Speed / Reset Simulation
            Change Water Temperature
            Change Speed of Day & Night Cycle
            Toggle Fog / View Distance
            Reset Player Position
            Volume
            Show Information on current numbers of simulated algae & corals
            Change Movement Speed
        Explore the reef at night with a (VR) flashlight
        Selfmade features to increase realism
            Water visualization
            Godrays
            Caustics
            Day & Night Cycle
            View Distortion
            Ambient underwater noise
            Particles
            Some fish have randomly chosen textures
        Intuitive movement with VR-Controller or Keyboard
        Some models use Parallax Occlusion Mapping for a more realistic appearance
        Triggerable event: Pulling an anchor through the reef, destroying generated corals and algae in its path
        Fish disappear realistically at night

                


Project Planning

Working with Scrum

For the master's project "VR CoralReef" we chose the Scrum model for managing the various tasks that approached each one of us. These tasks are stored in a Kanban board which we gradually implement. The whole group is responsible for updating the board. An important ritual are regular meetings where the whole group creates tasks and guesses the estimated amount of work (in points) for them, while each one contributes his or her individual skills and knowledge to the discussion. This ensures, that every member of the group is fully aware of each duty and its complexity.

For Scrum we chose a sprint length of two weeks, in which we complete said estimated and assigned tasks. In addition to the planning meetings regular retroperspectives are held in order to identify issues within the group as early as possible. Each end of a sprint privdes that we present our solutions to those responsible for the masters project and collect feedback (which is a phase also noted in the Kanban board). Subsequently we create a new set of tasks for the next sprint. While doing so, we try to keep the amount of work/point close to the project average so far.

Another fancied ritual for quality assurance is a regular code review where each group member chooses a part of code he or she wants to present and improve.

Scrum

Development process

In order to visualize the process developer and reviewer undergo, we created an abstract diagram of the development process.

Development process

Code Architecture and Diagrams

(free for non commercial use only but not commercial use -MIT License-)

SICCOM Plugin

The "SICCOM" Manager from the ZMT delivers raw data on birth, growth and decease of corals and algae, which are also fighting each other for dominance within the reef. The "VR CoralReef" takes this data directly and visualizes it as realistically as possible. Two of our members worked on a plugin for the Unreal Engine 4. Download the PDF below.

VR CoralReef: Reimplementation and Enhancement of the coral reef simulation SICCOM into the agent-based modeling framework FLAME

Swarm algorithms

We chose to base the algorithms of swarms, predators and lone fish on domain-driven design (DDD) - as far as practicable - in Unreal Engine 4. We could successfully discard the secondary ports, since UE4 already provides everything necessary. All algorithms work basically the same way, though the predators and lone fish own additional states, since they - unlike swarms - show varying behaviour.

The following diagrams describe the process per frame. Function calls are called by name and parameters, content of functions on the other hand only by abstract summaries.

Each frame triggers a tick event with the time that passed. This event selects the Actor class in the primary port in the adapter, which can seen in the diagram to the far left. These forward the events with necessary parameters to the manager class in the administration layer. The task of that manager class is to run the operations inside the domain in the correct order.

Until the implementation of the domain logic one can see, that the adapter and the administration layer are implemented mostly analogue. Inside the domain the functionalities begin to vary more, except for calculations of direction and position of the fish. For swarms these calculations are for social and individual forces and the potential occuring flee direction from predators.

Inside the domain, predators have states which influence the behaviour greatly, even though functionality of these states has been kept as low as possible. The two states are called "Travelling" and "Raiding". Each frame the administration triggers an event, deciding to stay in the current state or changing to the other one. A group of predators acts analogously, since they share states. Either they travel together - or they hunt together. Processing the forces of predators is simpler: since they ignore social forces, they focus on individual ones and hunting direction.

Individual/Lone fish have states inside the domain, which affect each of them individually. Since the states of individual fish differ more (compared to predators), they need states which can manipulate the fish completely. Until this point the individual fish travel through the reef or scrape on corals. Each fish decides individually, which coral it scrapes on. A synchronization is not happening. Once the set time for a state has passed, the fish will move on to the next state.

Ground Animals

Inside the Domain ground animals have a StateMachine, which analyzes - depending on its current state - the surrounding area of the animal for influencing factors. These factors can be objects standing in the way, other ground animals or the player. For each of these cases there are specific states, which alter the direction of movement. In case of a collision, for instance, a new path is calculated. If the player is close, ground animals can become aggressive or hide. Following the viewing direction and rotation of the ground animal will be adjusted depending on the alteration of movement.

States in general

The states of individual fish and predators work the same way. They have states switching into other states as soon as a set individual timer runs out. Until run out, the states receive constantly updated information on their respective movement direction. The moment a state runs out, it receives information which state is set next.

State transitions

There are three kinds of transitioning states:

The first group consists of "ScrapingTravelling", which makes the fish swim around until the "hunger" kicks in, "Scraping", which makes the fish dock and feed off a coral and "ScrapingUndocking", which makes the fish undock slowly until it finds himself in "ScrapingTravelling" again.

The predator logic can be summarized in a second group: "Travelling" makes them swim around in the simulation until several predators unite into the state "Raiding", attacking a swarm of fish until they go back to "Travelling", once "satisfied".

The last group consists of "Travelling" and "Center". These states make fish swim around and rotate them slowly towards the center of the simulation in order to make them not swim out of area.

Swarm Sequence
Swarm Sequence
Predator Sequence
Predator Sequence
Individual Fish Sequence
Individual Fish Sequence
Swarm Class
Swarm Class
Fish States
Fish States
State Transition
State Transition
Ground Animals
Ground Animals


          Swarms.Administration
            update(List fishes, float deltaSeconds)
                for(Fish f : fishes)
                    f.calcSocialForces(fishes)
                    f.calcIndependentForces()
                    f.calcAndUpdateVelocity(deltaSeconds)
                    f.calcAndUpdatePosition(deltaSeconds)

            Swarms.Domain
            calcSocialForces(List fishes)
                this.sumSeperationForces(fishes)    
                this.sumAlignmentForces(fishes) 
                this.sumCohesionForcesForces(fishes)    
                this.normalizeForces()

            Swarms.Domain
            sumSeperationForces()
                Vec3 sumSeperationForce
                for(Fish f : fishes)                        
                    if(f.position.distTo(this.position) < range)
                        sumSeperationForce += 
                            f.position-this.position

            Swarms.Domain
            sumAlignmentForces()
                Vec3 sumAlignmentForce
                for(Fish f : fishes)    
                    if(f.position.distTo(this.position) < range)
                        sumAlignmentForce += f.direction
                
            Swarms.Domain
            sumSeperationForces()
                Vec3 sumCohesionForcesForce
                for(Fish f : fishes)
                    if(f.position.distTo(this.position) < range)
                        sumCohesionForcesForce += 
                            this.position-f.position

            Swarms.Domain
            calcIndependentForces()
                this.calcTerrainAlignmentForce()
                this.calcTerrainRepulsionForce()
                this.calcSpeedAdaptionForce()
                this.calcPitchDampingForce()
                this.calcRandomForce()
                this.calcAttractionPointForce()
                this.calcFleeFromPredatorsForce()

            Swarms.Domain
            calcAndUpdateVelocity(float deltaSeconds)
                this.calcCombinedWeightedForce()
                this.velocity = this.velocity + combinedForce * deltaSeconds / this.mass
                this.direction = this.velocity.normalize()
            Swarms.Domain
            calcAndUpdatePosition(float deltaSeconds)
                this.position += this.velocity * deltaSeconds
                


          Predators.Administration
            update(List predators, float deltaSeconds)
                for(Predator p : predators)
                    p.updateState(deltaSeconds)
                    p.updateVelocity(deltaSeconds)
                    p.updatePosition(deltaSeconds)

            Predators.Domain
            updateState(float deltaSeconds)
                this.state.updateTimer(deltaSeconds)
                if(this.state.timeOver)
                    swapState()

            Predators.Domain
            updateVelocity(float deltaSeconds)
                this.calcPitchForce()
                this.calcTerrainAligmentForce()
                this.calcTerrainRepulsionForce()
                this.calcStateForce(this.state)
                this.calcDesiredSpeedForce()
                this.calcCombinedForce()
                this.velocity += this.combinedForce * deltaSeconds / this.mass

            Predators.Domain
            updatePosition(float deltaSeconds)
                this.position += this.velocity * deltaSeconds
                


          IndividualFishes.Administration
            update(List fishes, float deltaSeconds)
                for(Fish f : fishes)
                    f.updateState(deltaSeconds)
                    f.updateVelocity(deltaSeconds)
                    f.updatePosition(deltaSeconds)

            IndividualFishes.Domain
            updateState(float deltaSeconds)
                this.state.updateTimer(deltaSeconds)
                if(this.state.timeOver)
                    swapState()

            IndividualFishes.Domain
            updateVelocity(float deltaSeconds)
                this.calcPitchForce()
                this.calcStateForce(this.state)
                this.calcDesiredSpeedForce()
                this.calcCombinedForce()
                this.velocity = this.velocity + this.combinedForce * deltaSeconds / this.mass

            IndividualFishes.Domain
            updatePosition(float deltaSeconds)
                this.position += this.velocity * deltaSeconds