text:
MZR: Music synchronisation with a band-pass filter
This is how this game MZR happened to be. I always wanted to have visuals synched with music. That was integral part of the game idea so much that after some initial failures to get that going I gave up on the whole game for about couple of months.
Part of my inspiration came from early encounter in the XNA scene with ColdBeamGames' game Beat Hazard. (http://www.coldbeamgames.com/). An excellent example of how music synchronisation of visuals and game play can work really well. Definitely a direction I wanted to go towards although ColdBeamGames' stuff in that area is just on another level.
Again this is a vaguely technical post. It's going to be fairly simple stuff thought.
In order to synchronise visuals with music you want to be able to turn a waveform signal (audio signal) into a signal that drives your graphics. This can be done in couple of ways (that I know of):
- processing the raw audio input and extracting the amplitude of different frequencies (drums would be a fairly low frequency – for example 100Hz, voice is in the middle ones, etc). Then using that result signal to drive graphics.
- tagging – visualising the wave form and using a tool to place various events on the track, matching the beats and various other music facets. During game you can then synchronise the tag stream with the music stream and have the tags drive the visuals or game. I imagine that's how most "guitar hero" games are done.
Both approaches have advantages and disadvantages. Automatic processing can handle all sorts of music and produce fidelity you can't ever achieve with tagging. On other hand Automatic processing detects frequencies – it's simple as that. If you want anything more complex that is matched by something like a song chorus or a specific music phrase – you want tagging. Also nothing stops you form using both approaches together.
In MZR I use automatic processing. In this post I'll describe how got there.
I tried FFT first
Fast Fourier Transform is (better explanation from Wikipedia) an algorithm that can compute the discrete Fourier transform. A Fourier transform is one that can take a signal from time domain (amplitude over time waveform) to frequency domain (amplitude of frequencies). In essence you provide an array of values which is the sound (at 44KHz you get 44000 values per second) and you get an array of frequencies. In the frequencies array each item is the amplitude of that frequency.
You can find FFT implementations on the internet – there are ones in almost every programming language I can imagine. It's a known numerical recipe [points for those who got this pun ;)].
So, what do you do with this array of frequencies?
- find the dominant frequency – this is as simple as finding the array item with the largest value
- lookup a frequency range that you are interested in
- visualise it – in a traditional graphic equaliser the array items would each be a bar and the item values would be how high those bars are lit up
So why didn't I use this? Where's the gotcha with using FFT?
FFT is successfully used for this exact purpose. However I had couple of issues with this, some of them unrelated to the algorithm.
First and foremost I had made a mistake with my wave forms array calculations. Due to that I was feeding corrupt data into the FFT and was getting results that were really wrong. As there are complex numbers involved and I don't fully understand it I assumed I had implemented it wrongly or was using it incorrectly. The result after hours of experiments and visualisation was to abandon this solution and look for another one.
Another, not so valid reason is that FFT can be costly to calculate. I grew up in the '90 when we were counting every unorthodox operation and if simpler solution was available that could do the job that was the preferred solution. Today's computers even on mobile devices are pretty powerful and wouldn't bat a eyelid at this algorithm.
Not long after I had a chat and sought advice from a friend of mine – Neil Baldwin. He is far better informed in all matters audio, audio programming, audio electronics, music, etc… besides being an all round fantastic fellow. Checkout his site, especially if you like chiptunes and NES stuff – you wont be disappointed.
Anyway, that's when I learned about band pass filters.
Band-pass filter
You have probably heard of low-pass and high-pass filters, right? If not, a low-pass filter is one that once applied leaves only the low-frequencies in the signal. I'll leave you guessing what frequencies a "high-pass" filter leaves.
A band-pass filter is similar to the low and high pass ones but can be applied for an arbitrary frequency band. So you can say stuff like apply band-pass for a band that is centred at 440Hz and covered 200Hz each side. See the graph image at the top of the article and the link under it – that has a good and more in-depth explanation of what a band-pass filter is.
I believe my implementation was based on this internet post and code sample on the topic.
I thought the band-pass filter was a lot simpler to implement than a FFT and a lot easier to understand. I used it instead of my FFT implementation. No joy! That's when I left this venture and took a break.
Couple of months later…
… I suddenly realised that the problem wasn't with the FFT or the band-pass implementation. I had made a mistake of how I calculated the wave data size and converted the stereo channels into a mono stream to process. Once that was fixed, everything fell into place.
It's good to mention couple of things about debugging this stuff, even though I may not be the best person to advise on that given the above story. At least I knew I was doing it wrong and it was because I did this:
- visualise your input stream and output stream – I wrote a quick app in c# that drew the wave data and then overlay the processed on top – see if they matched. That's how you know the algorithm is working.
- play the music on top visualising the playback time to see if the processed data matches the music playback in any usable form. That's how you know you can use the output you are getting.
How did I end-up not spotting the problem then if I had such visualisation. My mistake was such that the calculated input signal data didn't match the length of the music. I was visualising only the start of the music track (a few seconds) and things looked ok-ish… however once used in game things quickly went wrong and I couldn't figure out why. Once I visualised the whole music track I could clearly see how the stream was ending well before the end of the music track. I guess the moral of the story is – if I have debugging tools I should use them in every possible way, not just in the one narrow minded approach I started with.
Actual game data
Once I got this working, I could see two ways to use these filters:
- pre-process the data offline and bake it into a file, then load in a game and use it synchronised
- use the live audio stream as sent to the audio output of the device and process that
I chose the first method. My decision was mainly driven by having to implement the audio output capture on multiple platforms. The iOS capture looked complicated enough. Plus, I wasn't planning on changing music tracks or using the user's music library (like Beat Hazard mentioned above).
I run 4 bands band-pass filters offline on all music tracks found in the game. I store the result at 60fps – my target frame rate. Each item is a vector4 with x,y,z and w being the output for each band – so I got 60 vector4 per second of music.
At game run-time I load the pre-processed data and track where the music playback has reached to – then I sample the vector4 value and attenuate it gradually in game.
That way in-game I always have a vector4 value representing 4 frequency bands that I can synchronise my visuals with.
Most of the time you don't have to deal with this. I mean signal processing is fascinating but it's hard to get right. Most game engines these days would have built-in functionality to give the FFT of an audio stream. That's right. For example Unity provides something called AudioSource.GetSpectrumData. Check it out.
That's it!
See you next time.
MZR leadergrid programming tricks
In MZR (now on App Store: http://bit.ly/MZR_Game) there is an alternative approach to the concept of leaderboards. As the height of the player's tower is the score we decided that it might be a good idea to have everyone else's tower around. See your friends and their scores at a glance. As they are all represented as square columns on a grid I call this the MZR leadergrid.
User can browse around, zoom in or out and see the global picture – scores aggregated by country as well as their friends.
In this post I'll talk about the leaderbaord implementation. In general it's a collection of programming tricks and shortcuts and I wanted to describe some of those.
Most of the techniques are aimed at providing visual complexity while reducing the number of draw calls. High number of draw calls is possibly the main thing that would hurt your performance – any opportunity to reduce that number without impact on quality should be considered.
The implementation of the MZR leadergrid score representation is split in two parts.
- The local grid where every tower is an accurate representation of a real active player.
- The global grid where a representation of the global leadergrid is rendered based on aggregated data from our servers.
Local grid
Local in this case refers to the locality of the other users' towers to the centre player tower. There is a grid of 9×9 towers around the main one.
This local grid, contains a few types of entries:
- friend entries – these are the towers of friends logged in Game Center or Facebook. Every friend gets their avatar picture on top of their tower, as well as their score
- active player entries – there are towers of players who have played the game recently. The idea is to get a selection players who are currently playing the game.
- global grid entries – these are entries that could not be filled by friends or active players and are sampled in a similar way as the global grid one (described below)
In a way this local bit is the "friends" section of a normal leaderboard but extended so it can always fill 9×9 matrix.
This local grid is the immediate vicinity of the player playing field and as such visible during gameplay. I also wanted to indicate on the nearby columns (towers) how the current player score compares to them.
The local grid is accurate. Every column (friends and active players) is an actual player with their score as reported by our servers. Every time a player submits a high-score to the servers, it is stored in our database and then reported to the player's friends when they play.
Rendering of the local grid
All of the columns in the local grid are a single rendering mesh. That allows efficient draw call submission – 1 call is better than 9×9 calls. The writing and avatars on top are additional draw calls as they are translucently blended on top. That also allows me to dynamically alter/grow columns as players upload higher scores. Each column is always in the same place in the vertex array so I can calculate what part of the vertex array I'm changing when the column grows.
A similar approach is taken with player scores. A single draw call renders all players score. They use the same font and can change dynamically. That's possible because I always leave space in the vertex array for 4 digits. By using degenerate (zero area) triangles I can display scores that with less than 4 digits while maintaining vertex count for the full 4 digits.
Finally the avatars. The avatars can change at any time as player logs in to Game Center or Facebook and gets lists of friends… and their avatar pictures are downloaded from the respective network. Furthermore, to optimise the draw call for those avatar images they need to be in the same texture – not separate textures. Again a single draw call is a lot better than 81 (9×9) ones.
To achieve that I pack all images into a dynamic texture atlas. I use a render-to-texture technique to pack each avatar picture into a separate place on the same texture. Then I just need to update the display avatar mesh with the right texture coordinates of where that avatar image finds itself in the final atlas texture. A bonus of this atlas rendering is that I can apply a custom shader effect to the avatar images achieving the specific MZR look they have.
Finally I have the hight indicators rendered on the closest friend columns indicating how high the current player run has reached. At the same time if a local grid column is overtaken, it would flash briefly by changing the colours of the appropriate vertices in the grid vertex array.
Global grid
The global grid is everything outside the 9×9 local grid. It repeats infinitely the space so the user can scroll around in any direction when they browse. By repeats infinitely, I mean that the camera is telported back once it reaches certain limit – wrapping back to the opposite side of the area – that gives impression of endless scrolling.
The global grid is not a 1-to-1 representation of all the players in the world. It is a statistical representation. This is done for couple of reasons:
- to reduce the data transfer between the app and our servers
- to show the player a bigger picture about the scores of the world.
To achieve that I do a certain aggregation on the server with respect to players scores. At regular intervals a routine runs that calculates stats for every country in the world. The stats calculated are number of players from that country, the average score for that country and the maximum score.
The game client downloads the country score stats from the server. The global leadergrid is then rendered using that information. You can look at this from a data compression point of view: it's a loss compression method where the data aggregation is the compression and the visualisation is the decompression part.
In terms of visualisation each country looks like a small mountain of columns. The more people play in that country the larger space it occupies. The top score for that country is the highest point of the mountain. The average score of the country dictates how "sharp" the mountain is. If the average score is low (a lot lower than the max one) then we get a mountain that's fairly pointy – naturally the people with high scores are not many. If the average score is high, then we get a meatier mountain as there are more people with relatively high scores.
I achieve that by using a power function to approximate the curve slope. I take the average score (av) and the max score (max) for a given country and calculate the ratio as av/(max*0.5). That way score average that is half the max score for that country would mean a power of 1. Say we have average score of 50 and max score of 100 – give the formula we get 50/(100*0.5)=1. We then use the function f(x) = 1-pow(x, av/(max*0.5)) to get the height at various point of x where x is the distance of the sample point form the centre of the country region.
Note: the mathematical ground behind this was if we imagine these mountains as cones (or a swept/revolved curve that makes a kind of a strange cone) then the volume of that cone would be the total added scores of all players playing. That can be found by calculating player scores x average score. We know the height of the cone (max score) and the radius of the cone (number of player playing). Having the radius and the height of the cone the unknown would be the curve which swept would dictate the volume of the "cone". The connection between the curve and the cone volume would be an integral of that curve over a circle.
Solving this however goes beyond my mathematical skills and seemed extremely OTT when I had a sensible approximation already.
Global grid country field
Once the country scores have been downloaded from the server. They are inserted into a CountryField object that places them on a plane and uses a relaxation algorithm to make sure they are spaced evenly according to their respective radius. After that I can query the CountryField at any point in the world and it will return a height for that point based on what countries overlap and influence that point. The relaxation is seeded randomly so that every time a user gets the countries from the servers the global grid looks different.
When sampling at a certain point I consider all countries that the sampling point overlaps with. Then I apply a calculation described above and take the highest sample position. Layered on that is a deterministic noise function so that the score mountains don't look uniform.
The rendering routine then uses this CountryField object to sample the heights for each of the global grid columns.
Adaptive subdivision
Rendering all global grid towers in one go proved slow – too much geometry to update at the same time. I opted out for an adaptive subdivision technique where if columns are close to the camera then they are rendered if they are further away they get converted into a bigger column that's the average of their height (it's actually biased above the average as that proved better looking). This is done on 3×3 columns basis. As camera moves around some of these combined columns split up dynamically and other coalesce. This combined with some non-linear interpolation gives the unique MZR look when user is browsing around.
This adaptive technique also means that geometry rendered is kept under control.It also allows the adaptive algorithm to work on only fraction of the geometry to interpolate and update the vertex array. The entire global grid is a single mesh and there for a single draw call.
Country names
On top, like clouds, are rendered the country initials (alpha-2 country code) and the country top score. This is again a single mesh so I can render that in a single draw call.
MZR has unique look when it comes to leaderboards. In some ways however it is a bit "style before function". That's ok. MZR has always been about trying something new, be willing to go where traditionally games have done stuff another way.
With that in mind here's what I think could be better:
- No easy way to compare. In a traditional leaderboard user gets a list of entries with them inserted in the middle. They immediately know who is ahead of them and behind them. This information is more difficult to read in MZR. User gets a bigger picture view but details remain a bit hazy – the details are still there but not so easy to compare.
- No easy way to compare country scores. User has to browse around Its' been fun to watch different countries take the lead (as of writing of this post Canada has the lead) but it would have been better to have a clear indication of who is in front.
- In retrospect just using alpha-2 country codes make for a more alienating experience. Using something like full names or flags would have work better.
That's it. If you are interested in reading more about any of the areas I describe, do let me know and I can write that up in more detail in a separate post.
See you next time.
Blending and Transitioning Camera Behaviours
This time I'm going to talk about an approach I've used successfully on multiple occasions in several companies and home projects. I use it to manage multiple behaviours, blend and transition between them.
I've used this system for animation blending and camera control in the past. However, if I can represent something as a state structure and want to blend/transition between different behaviours that operate on that state then this is my "go to" solution.
In MZR I use this approach for my camera system as well as a system that adds additional camera effects – shakes, wobbles, etc. They are both independent: the camera may have a "focus on point of interest" behaviour to control it while the effects can change independently of that giving me a wider variety of visual experience.
The main motivation behind a system like that is that we want to be mostly concerned with directing the system behaviour rather than be busy with the small detail of how that happens every time. I'm interested in when the camera transition happens, how long it lasts, what the new camera frame is, etc. I'm less concerned with what happens with the old camera setup and I'm definitely not keen on doing the same work every time a camera transition needs to happen, in terms of maintaining entities and writing code to manage their life time.
Ideally we want to write only the code that introduces changes in the system and have the system sort itself out afterwards.
First things first.
Couple of words about some code choices.
In order to get automation of allocation and deallocation of objects I make use of a smart pointer system. If you are working in a managed language environment (like C# for example) you don't have to worry about that. However, for the purpose of this article if you see an object that is derived from BaseObject then it supports intrusive reference counting. And if you see SmartPtr<MyClass> then that adds value semantics to the pointer – incrementing, decrementing the ref count of the object to manage its life time.
In short it's an automatic lifetime management system. If noone is pointing to an object it will get deleted.
The State
I use a POD type of structure to represent the state of an item in the system. In this example the we are doing a camera system so let's represent the state as two points: camera position and camera target. You can use a position and orientation or any other combination of properties.
The state is important because this is the result of our system. It is also the data that we would blend. Any behaviours we have will aim to produce one of these states as result of their execution.
struct CameraState { Vector3 position; Vector3 target; }; CameraState BlendCameraState(const CameraState& lhs, const CameraState& rhs, float fraction) { CameraState result; result.position = lhs.positions*(1.0f - fraction) + rhs.position*fraction; result.target = lhs.target*(1.0f - fraction) + rhs.target*fraction; return result; }
The state can be anything. In case of an animation system the state can be an array of skeletal bone transforms, movement vector extracted from the animation and so on.
The Base Controller
Next, the basic building block of my system – the CameraControllerBase. It contains a state that we can get access to in order to find out the current state of the system.
class CameraControllerBase: public BaseObject { public: virtual SmartPtr<CameraControllerBase> Update(float fDeltaTime) { return this; } const CameraState& GetState() const { return m_state; } protected: CameraState m_state; };
The most important part of this class is the Update method. The update is where a derived behaviour would do the work by overriding that method.
The Update returns the current controller the parent entity would have after this update step. At the top level, let's say the entity that owns the system, we have a pointer to the current "top" controller.
SmartPtr<CameraControllerBase> m_topController;
In the update part of this top level entity we want to update the current current top controller and assign to it whatever it returns.
void Game::Update(float fDeltaTime) { ... m_topController = m_topController->Update(fDeltaTime); ... }
By doing this we make sure that whatever behaviour is currently at the top controller will be updated and can delegate it's position of "top controller" to one of it's child behaviours it aggregates.
This is the driving idea behind this approach. Controllers can "suicide" themselves and pass the responsibility of top controller to another controller they hold a pointer to.
In this article I use the terms controller and behaviour interchangeably. My base building block is the controller – but some controllers have more complex functionality that is beyond the simple control/blend functionality of the system. In other words they have some game or domain specific function that is used to generate or process a state. I call such controllers "behaviours" to indicate their higher function.
The Blend Controller
The blend controller is a class that takes two other controllers (of unknown type but derived from the base one) and blends between them over time. Then it replaces itself with the second controller – the one it interpolates to. As it replaces itself with the "to" controller the "from" and the "blend" controllers are automatically disposed of.
It's a transition.
class CameraControllerBlend: public CameraControllerBase { public: CameraControllerBlend(SmartPtr<CameraControllerBase> From, SmartPtr<CameraControllerBase> To, float BlendTime) { m_blendTimeMax = BlendTime; m_blendTime = 0 m_controllerFrom = From; m_controllerTo = To; } SmartPtr<CameraControllerBase> Update(float fDeltaTime) { // accumulate the time m_blendTime += fDeltaTime; //update the two controllers; assign the result of the update them so the take over logic works m_from = m_from->Update(fDeltaTime); m_fo = m_to->Update(fDeltaTime); if (m_blendTime < m_blendTimeMax) { float fraction = m_blendTime/m_blendTimeMax; //use fraction to blend between the states of m_From and m_To //store the resulting blended state in m_state of base class m_state = BlendCameraState(m_from->GetState(), m_to->GetState(), fraction); // return this one as the current top controller return this; } else { //the blending has finished - return the m_To controller as one that will take over return m_to; } } private: float m_blendTime; float m_blendTimeMax; SmartPtr<CameraControllerBase> m_from; SmartPtr<CameraControllerBase> m_to; };
To trigger this transition we we have to replace the top controller with a newly created blend one that blends between the old top controller and a new behaviour.
void Game::BlendToController(SmartPtr<CameraControllerBase> ToController, float BlendTime)</pre> { m_topController = new CameraControllerBlend(m_topController, ToController, BlendTime); }
Easy. With just one line we can introduce new controller/behaviour in the system and have it blend in gracefully and clean up after itself.
A really nice property of this system is that if blend transitions come in close succession (before the previous blend has finished) everything works exactly as expected. By doing that we are essentially growing the three of objects with every branch being a blend controller pointing to either other blend controllers or behaviour. In the end once all blend times have expired we will be left once again with one top controller.
Sometimes we want to blend to a behaviour, stay at that behaviour for a while and then return to the previous one. I call that an "attack-sustain-release" blend controller. The controller blends to the "to" behaviour, stays there for "sustain" time and in the end returning the "from" controller and disposing of the "to" one.
Here's how this "attack-sustain-release" (ASR) controller Update function might look.
SmartPtr<CameraControllerBase> CameraControllerBlendASR::Update(float fDeltaTime) { // accumulate the time m_blendTime += fDeltaTime; //update the two controllers; assign the result of the update them so the take over logic works m_from = m_from->Update(fDeltaTime); m_to = m_to->Update(fDeltaTime); if (m_blendTime < (m_attackTime + m_sustainTime + m_releaseTime) { //calculate fraction as function of current BlendTime, attack, sustain and release times //fraction will stay in the range [0:1] float fraction = CalcAttackSustainReleaseFrac(m_blendTime, m_attackTime, m_sustainTime, m_releaseTime); //use fraction to blend between the states of m_From and m_To //store the resulting blended state in m_state of base class m_state = BlendCameraState(m_from->GetState(), m_to->GetState(), fraction); // return this one as the current top controller return this; } else { //the blending has finished - return the m_From controller as one that will take over return m_from; } }
The fraction function returns a value between 0 and 1 depending which phase of the controller we are in. During "sustain" fraction will always be 1 for example.
Behaviour Controllers
We had a look at the blend controllers but what about the actual behaviours in the system? Well, that's down to the specific system. That's why our Update function is virtual, so that any derived classes can calculate the state in many ways not imagined by us at the point of writing the system.
For a camera system here are some that I've used in the past (Note: names are something I've just come up with):
- CameraControllerSnapshot – take a snapshot of a current CameraState and keep it still – in many ways that's the CameraControllerBase with ability to expose the m_state for writing.
- CameraControllerFixedPointLookAtPlayer – one that keeps the camera in the same position but makes it look at the player and track them
- CameraControllerFixedDirectionLookAtPlayer – camera looks at the player from certain directions and moves position to maintain that direction as that player moves. Often such camera would be constrained by a box or geometry.
- CameraControllerRailsLookAtPlayer – this is sort of cinematic camera 3rd person action games would employ. It would constrain it's position to a pre-defined spline (on-rails) and follow the player.
- CameraControllerRailsFixedLookedAtPlayer – this is a variant of the on-rails camera where there are two splines. One that defines the camera position and another one that defines the camera look-at point. This is used so that at any point the artist (camera man) knows what will be in the frame. We would then take the player position, find the closest point on the target spline and calculate the position spline accordingly.
I'm sure you can come up with a lot more camera behaviours. This is just a taste. As long as your Update function uses some logic to fill the m_state CameraState you will have a working system.
Non-transition blending
Not all blends are transitional. They don't have to be timed and always expire.
We could have a behaviour that has two child behaviours – very much like our blend controller. However instead of time controlling our fraction we can control it from another parameter in code or data setup. That way we can dynamically control the degree in which each of the child behaviours contribute to the final state.
You can take this notion a step further and introduce several child behaviours that are all associated with a value on a line – for example one sits at 0, one at 0.5 and finally one at 1.0. Then the blend behaviour would be given a parameter "depth" and it would evaluate which child behaviours contribute to the final output. This I've heard that called a "depth blend".
There could be other blend examples where the parameters are not linear. Any parameter set can be used as long they can be evaluated to result into a weight for their corresponding child behaviour contribution.
I've mostly used these in animation blending. For example, the depth blend could be used in character animation where we want to blend between two animation loops: running and walking. Based on the desired speed of the character we can derive a parameter that is the fraction between walking and running speed and pass it in as depth blend factor. The result would be an animation that is half walk and half run driven by the parameter we just passed in.
Another animation example would be the multi-parameter blend. Let's say we have several animations of a character that is pointing [a weapon?] at different directions. Each of these animations is associated with it's corresponding aim direction. Given a desired aim direction the system evaluates a function that results in an array of weights – one for every animation. Using those weights we can then calculate a weighted blend of those animations to got to a state where we have a character pointing at the direction we need.
Note: there is a lot more going on in character animation systems and I'm simplifying here to illustrate this method. A good animation system would need to compensate for different character speeds, foot planting, make additional corrections using IK solutions and so on.
In practice…
… I have a generic template implementation that I specialise every time I have to write one of these systems. The blend controllers are the same. The state, the state interpolation function and the behaviours are what differs between systems.
Sometimes you will need different interpolation methods than just a linear in transitions. You can add that to the blend controller and control it with a parameter.
Depending on the game that you are making you may even want to make the blending controllers be more context aware. Maybe you want your camera to always track the player no-mater-what. Maybe sometimes blending between two perfectly good behaviours you end up with a frame or two when the camera isn't looking at the player. To fix that you could make a "clever" blend controller that blends between two controllers but keeps the player into view.
You can trigger camera blend transitions in code – I do that in MZR. However, quite often camera transitions and blends are result of a complex setup in a level. When player passes this trigger then transition to this camera and if they get in this area switch that one, etc. You can even have an editor that allows you to lay down those triggers and position the camera behaviours around the level… but that's another story.
That's it for now. I hope you enjoyed reading about this system. It has served me well and I like how it liberates me from the tedious book-keeping of the blending transition tasks and allows me to focus on the top line "what I want to happen" bit of development.
See you next time.
MZR: Gradient Based Shader Effect
Today I'll talk about a shader idea I've always wanted to use but never got to release in a game until now. It has its roots in the old retro palette scrolling technique – or at least was inspired by it.
Palette scrolling was the thing when images had 8 bit pixels with each pixels being an index into a palette table of 256 RGB entries. That way using the same image and just changing the palette, one could change the look of the image without actually altering any pixels. Artists would do wonderful animations with just changing palettes. One of the cheapest way to do that would be to just shift the palette one entry (scroll it) and then see the colours shift – I called that palette scrolling.
These days one can still do palette scrolling but on current GPU hardware that involves using two textures: one index texture and one 1D palette texture. Animation being achieved by dynamically changing the palette texture. While on desktop GPU hardware that's entirely fine on current mobile device GPUs dependent texture fetches are not very performance friendly.
I wanted to use a similar concept of having a static texture that would change appearance when "something like a palette" would change.
I do that by exposing a range from a gradient texture using a step function. For a quick refresher on the topic, have a look at this excellent post on step and pulse functions: http://realtimecollisiondetection.net/blog/?p=95
By using a gradient texture and a step function, y = sat(ax + b), I can vary the parameters and a and b and reveal/animate different parts of the said texture. I also introduce two colours and interpolate between then based on the y value.
Here is the shader code:
uniform mediump vec2 GradientParams; uniform lowp vec4 GradientColour0; uniform lowp vec4 GradientColour1; ... mediump vec4 col = texture2D(Texture, texVar); // calculate a*x + b mediump float y = col.x*GradientParams.x + GradientParams.y; // calculate sat(a*x + b) by clamping y = clamp(y, 0.0, 1.0); //sat (a*x + b) // interpolate the two colours based on the resulting y value lowp vec4 rcol = GradientColour0*(1.0 - y) + GradientColour1*y; // factor in the original texture alpha col.xyz = rcol.xyz; col.a *= rcol.a; //apply the variant colour gl_FragColor = col*colorVar;
The a and b parameters go in the GradientParameters x and y components and two colours at each extreme is respectively GradientColour0 (for y=0) and GradientColour1 (for y=1).
Let's take a simple gradient texture:
And then apply our shader to it. We are using the function y=sat(ax+b). We use a=1 and b=0 thus giving us a gradient of 0 to 1 in the range of the texture. Then we are going to assign a colour at y=0 to be white (255,255,255) and at y=1 we'll assign it to be black (0,0,0). Here's how that would look.
Next let's try to use a part of the range. We'll use the same function but use a = 3.3 and b=-0.9. That way y will be 0 until x reaches 0.3 and then grow linearly to 1 until x reaches 0.6. To illustrate that I've assigned colours to be red for y=0 and blue for y=1.
Here's one based on the same gradient texture that illustrates the way I use this effect. I assign a=2 and b=0 and that gives me a gradient between 0 and 0.5. I also assign the y=1 colour to be translucent – alpha=0.0. That way by varying the parameter a with some dynamic game value, I can get the bar to move with that value.
In MZR I link a lot of effects to the music EQ so that visuals appear to bounce with with music.
The above examples are using our simple horizontal gradient texture. Things get a bit more interesting as we start using more complicated textures. For example here's the actual texture I use for my effect in MZR and the final result next to it. The green MZR logo in the texutre is to indicate where the start of the gradient is – it's a grey gradient that fills up a maze.
And here's the intro sequence to MZR where this effect is used:
The parameters are linked to the music EQ. The video shows the effect which is a single render call as well as the logo rendered on top and a FUNKY CIRCUIT sign underneath.
That's it for now. See you next time.
The 1D Radial Height Field
It is common in games to use a generic, complex and powerful system to solve a small simple problem. There are many reasons for that:
- developer is familiar with the system/tool – familiarity – we work faster with the tools we know how to use!
- it's available and needs no additional work – reuse – saving effort and money!
- seems like the right "realistic" way to solve the problem – stay grounded
- will solve the problem in all possible scenarios that would happen – be robust
All good reasons and I'm sure there are more. To illustrate this let's take game physics and collision detection – often such a system in games. They can:
- check for "line-of-sight"
- use custom colliders (invisible walls) to solve game play problems
- use it to ensure camera doesn't get in a place where it won't provide useful view to the player
These sound so common and natural. They are now standard uses of these systems in games and many people often wouldn't think twice if they had to solve one of the above problems. I'm sure you can find other countless examples.
… I want to talk about using a custom solution to solve a problem that would otherwise be solved by a generic system. In Mazer that would be the camera control and not letting it get in a place where random geometry would obscure the player's view.
In Mazer the camera always looks at the top of the maze tower the player is constructing and is surrounded by other "leaderboard" towers. The camera position however is procedurally and programatically controlled to be "interesting" and "cool" with the music and gameplay. It can happen that the camera would intersect with surrounding towers obscuring the player's view and rendering the game unplayable.
Simple brute-force solution to this problem would be to construct a camera frustum and check all surrounding towers for intersection. Easy enough to implement that solution has one major problem – it only provides us with the information that something bad has happened but not with the information needed to resolve the situation.
Next, more elaborate algorithms can be involved where we can have objects be physical entities (rigid-bodies) and just let them collide and slide against each other – never to intersect and get the player in trouble. That would solve the problem and perhaps look good too – one can never be sure before it's implemented. However, it would be like using a massive hammer to hit a tiny nail.
The solution I use in Mazer uses a more simplistic yet robust approach. It is based on the knowledge that the camera is not completely free and there are various constraints that allow us to solve that problem in a different/targeted way.
Height Field (1D)
First a small detour into height fields. A height field is a scalar field of heights. Quite often you'd see that as a terrain representation where given 2D coordinates you can get the height of the terrain at that point.
A simpler form of this is a 1D height field. In essence that is just a function where given one coordinate "x" and evaluating the height field function h(x) you can get the height (or "y" coordinate).
This can be achieved with a polynomial of some fashion. For example f(x) = 2*x – x*x. That way we have a continuos solution and a known function that gives us a value at every (most) values of x.
However, if we have some data and we want our height function to match that data we can use an array of control points that specify the height at various values of "x" and an interpolation policy allowing the function to give a continuos result for any value of "x" (Figure 1). I find this to be a common scenario throughout development.
I'm using a linear interpolation here but a more complex methods of interpolation can provide a better (and higher order) continuity.
Height Field (1d) on a Circle
Note: if anyone knows a better name for this method (there must be one), please let me know.
Now imagine we wrap the 1D height field over a circle. Now x is the angle in radians so any values outside the range of [0; 2*π] are equivalent to that range. So we need to define our h(x) just for that range.
If we have h(x) =0, our Circle Height Field will be just a dot. If we have h(x) = 1, our field will be a circle with radius 1.
Figure 2 illustrates how our 1D data points height field above translates to this idea. It is the same field with the same data points but now plotted on a circle.
In code, I often need to plot the circle height field so I can visualise it and troubleshoot problems with my code. To do so we need to get a 2D point for every value of x. Here's how we do this:
Vector2 GetCircleHeightFieldPoint(float x) { //calculate the unit vector at X angle Vector2 unit = Vector2(fcos(x), fsin(x)); //get the height at X angle float h = HeightFieldFunction(x); //combine them to get the point on our circle height field at that angle return unit*h; }
By iterating a number of values of "x" in the range of [0; 2*π] we can get a full representation of the radial height field. All images below (screens from Mazer) use this method to visualise the field.
Camera Control
How is that relevant to camera control?
I calculate the area the camera can go without getting the user in trouble. I start with and empty height field function h(x) and then I plot, in the height field, all the obstacles that can obscure the camera view. In my case each obstacle is a box. Once projected on a circle it becomes a curve segment that I have to draw (project) on my h(x). There is more information about this process below.
Once I complete that I have a h(x) that gives me the maximum distance (height) the camera can be in at every angle. If I keep the camera within that limit I know I won't get any visual problems. Even more, if I find that the camera has strayed into an area that is "not good", I can immediately take remedial action in the right direction or quickly evaluate many other potential points the camera can go very cheaply.
For now I'll just show a simple method that limits the camera within that height-field – if it goes beyond it, it limits the camera to the maximum distance.
Vector2 LimitCameraPosition(Vector2 cameraPosition) { //get the "height" the current camera position is at float height = length(cameraPosition); //normalise to get the unit vector Vector2 unit = normalise(cameraPosition); //convert to angle representation float angle = UnitToAngle(unit); //look up the height function to get the max height at that angle float maxHeight = HeightFieldFunction(angle); //limit the distance to that max height if (height > maxHeight) { return unit*maxHeight; } return cameraPosition; }
In the code above there is a function to convert from a unit vector to an angle scalar (in radians). While that's trivial using an atan2 function from the standard library, you have to remember to wrap that around and keep the angle in the range of [0; 2*π].
float UnitToAngle(const Vector2& unit) { //get angle float ang = atan2(unit.y, unit.x); //keep it in the range if (ang < 0.0f) ang += PI*2.0f; return ang; }
Obstacle Drawing: Preparing a Useful Height Field
Now that we have the basics of our radial height field for camera movement we need a method to insert useful data in it. The method I use is to initalise the field to some default maximum value – at that point it's just a circle with radius of "maximum value".
Then I "draw" various obstacles that in-turn would "dent" the circle and make the function non uniform. In the Mazer case the obstacles are the "score" boxes.
For each box I find the bonding circle of that box in 2D and then from the centre and radius of that bound sphere I find two points determining the extents (in the height field circle) of the arc that it would take. Then I step through the line segment those two points define intersecting a ray (starting at the origin and pointing towards the step point on the segment) with the box obstacle itself.
Then I check if the distance to the intersection point is less than the distance stored in the closest control point in the field function and write it in. In a way this acts as a 1D circular depth-buffer.
Finally I do a low pass filter on the data (field) so that all edges are smooth and provide a more gradual response when I use it for camera control.
I look up the constructed field multiple times a frame. However that would be only for certain values of "x".
Most performance hit is taken when I'm constructing the field and rasterising the obstacles in it. Right now I do that every frame and it has a resolution of 128 control points for the whole range of [0; 2*π]. That gives me a good resolution for quality camera control and I haven't seen any visible performance impact.
Other Applications
I'm sure this method has it's applications in game AI. I know I've seen this visualised before in games (or debug information in games) and that's how I got to know about it. I can think of AI agents using it to plot a 360 degree of threat so the AI can reason about the best course of action for that agent. Or maybe representing the audio "hearing" of the AI agent so it can reason about where the sounds are coming from and how to react.
This approach also shares similar ground with the "context maps" described in this post by @tenpn http://andrewfray.wordpress.com/2013/03/26/context-behaviours-know-how-to-share/
That's it for now. See you next time.
Mazer: Wavefront
I first learned about this algorithm when I was at school. I needed something to fill a maze with certain values and I was going for a brute-force flood-fill recursion when my teacher suggested I should use a wavefront.
Note: what I call wavefront propagation is a simplified version of Dijkstra's algorithm. (Thanks to @tenpn for pointing this out)
So how does wavefront propagation work?
Suppose you want to fill a maze (or any connected graph) starting at a certain point in the maze. With a wavefront you:
- Mark that node in the maze – mark it with 1 as this is the first step in the wavefront propagation – then you insert it in the wavefront queue.
- Pick up a node from the "wavefront" queue (FIFO). Examine it's wavefront value and make that current wavefront value.
- Examine all neighbours of the node in the graph. For any neighbours that are unobstructed and have not been visited yet: mark them with wavefront value + 1 and insert them in the wavefront queue.
- Repeat steps 2 – 4 until the wavefront queue is empty – i.e. no work left to do. All reachable nodes, that could be reached from the start, have been visited.
At this point you should have a maze that has been marked with wavefront values that represent the distance to travel to the start point. A distance field of sorts.
How is this useful?
1. Path-finding. Let's say that we have two points in a maze – a start point and a destination. You can start a wavefront at the destination (yeah, it's a bit backwards) and propagate it until the wavefront reaches the start point. After that "the path" is just following neighbours with decreasing wavefront values.
2. Distance map. Path finding is usually about finding the shortest path… using wavefront we can build a map of how far it is to travel to the destination at every node. That allows not only multiple agents to look-up and path find at zero cost (to the same destination) but also make decisions if they want to take a different path at any moment.
3. Multiple destinations. By slightly modifying the storage at each node we could have multiple destination wavefront values stored at each node – by storing an array of values instead of just single value. Then we can have hundreds or thousands of agents seemingly all efficiently path-finding towards their chosen destination while incurring 0 cost run time because it has all been encoded in the maze.
But what about the costs?
Wavefront has certain resource overheads. It has a queue that would grow up to the length of the current wavefront. And it would be more conservative than a heuristic based path-finding algorithm for example A*. Wavefront aimlessly fills the whole maze – it doesn't target a certain destination.
These resource concerns can be addressed in various ways and quite often depend on the actual application. The two most often applications I go for are:
- pre-computation – using wavefront offline in a tool to compute the distance map and then save the data to use run time. This can also be in-game at level initialisation time. I used that in Carcophony
- time-distributed iteration – instead of propagating all wavefront completely on one go and fill the maze at once, I can do one node (or one wavefront value) at time… spreading the cost over multiple game frames. In Mazer I do exactly that – spread the cost over multiple frames.
How is this NOT useful?
Even though I like this algorithm, no doubt due to my early encounter with it, it can be very limited and grow complicated as we try to overcome it's limitations. Arbitrary costs to traverse a node or node links for example… Carcophony had to deal with that as roads were of different length and not all neighbours are the same distance away.
Wavefront takes centre stage in my new game (codenamed Mazer for now). In that I try to make a game mechanic out of my nostalgia for a programming algorithm I learned very early on. I hope you grow to like it too.


text:
Seating capacity 60
Width: 10 metres
Length: 11 metres
Height: 5 metres
Surface area: 100 sq. metres
Depth of speaker platform: 3 metres
The twin Jacopone da Todi and San Bernardino da Siena rooms are identical, and can each seat up to 60 persons.
Spacious, quiet and bright, they are fitted with practical armchairs in Estel leather that make them particularly comfortable and versatile.
video projector | motorized 16:9 screen | DVD player | speaker table microphones | podium microphones | handheld wireless microphone | audio and video recording | telephone | audio and video links to and from other rooms | automated dimming curtains

subset: commoncrawl


text:
Craft. Culture. Camaraderie.
It will be worth your wait
A Review of Hopslam by Bell's Brewery, Inc.
Posted on 8/24/2011 by
Brew's Your Daddy
I have joked before about how I would like to write a review on a beer by Bell's Brewery, and just put ''It's brewed by Bell's. 'Nuff said.'' If you have had any offering from Bell's, you can understand why I could justify writing a review that short, and still be 100% right. They are one of those breweries who just seem to get it. I would put any of their offerings against ANY other breweries version of ANY style. You want a good lager? They have one. You want a good stout? They have several. You want a good seasonal? They have you covered. And that is what brings me to the Hopslam Ale. The Hopslam Ale is a winter seasonal, double IPA brewed with six different types of hops that is then dry-hopped with Simcoe hops. Then somewhere in that process they had the brilliant idea to add honey to it just for good measure. Now let's not dwell on how I managed to get my hands on one of these in perhaps the hottest part of summer. You are better off not knowing. Instead, lets dive in and let me share with you what is truly one of the jewels of the craft beer world crown.
When you pour it, the Hopslam looks like a glass of melted butterscotch with whipped cream on top. I think the helpful pic really is worth a thousand words here. This beer is really an eye catcher. You can smell the floral hops jumping out of the glass before you even get a chance to lean towards it. Once you do manage to get close to it, the citrus hops start to come through. Grapefruit and passion fruits are easily detected. And about the time you start to really get into those citrus notes, the Simcoe hops make themselves known. They really are one of the only types of hops that are unquestionably detectable and distinguishable when they are used in a beer. Once you get past the abundant layers of hops, you can start to pick out a nice malty layer, and then the honey comes in. Oh the sweet honey. It just gives an added layer of sweetness to this beer that, as it turns out, is one of the most balanced imperial IPA's that you will ever get your hands on.
I would suggest you take a seat before you take the first sip. The Hopslam Ale is one of those beers that will make you weak in the knees with satisfaction. The hops, as with most imperial IPAs, are right up front and give you a nice little bite from the word go. Not from aggression, but more so with the grapefruit flavor. Not to worry though. Before your brain can even register that this one is loaded with hops, the honey jumps in and coats your mouth with a nice, calming layer of sweetness that balances out the hops perfectly. The malt that was noticed in the nose makes an appearance on the back end, and does a good job in finishing up the flavor train. There isn't really any sign of hops bitterness in the aftertaste, and all you really end up with is a nice, sweet, flavorful hoppy finish.
And as if the aroma and taste descriptions aren't enough to make you willing to offer your first born for one of these right now, the mouthfeel just shoves it above and beyond any and all of its competition. This is one of the smoothest drinking imperial IPAs I have ever had. The amazing balance in the flavors, along with a spot on level of carbonation needed to carry those flavors, give the Hopslam a level of drinkability that is dangerous. Why do I say dangerous? Maybe I failed to mention that this beer clocks in at a whopping 10% ABV, and you can barely even tell that it's an alcoholic beverage. Now you can consider yourself warned.
I have stated numerous times that there are a few breweries that seemingly can't miss. Bell's Brewery sits right at the very top of that list. I don't care which of their offerings you have in your hand, you have a hard time not saying ''This is the best (insert beer style here) I think I have ever had.'' I have no problem telling all the more experienced drinkers out there to grab up a couple of six packs of these as soon as you can find them on the shelves. This one is really a treat for those of you who can appreciate the amazing job that Bell's has done here. Hopslam is a great example of the perfect balance of flavors, aromas, and drinkability all in one bottle. I would tell those new to the better beer world to proceed with caution on this one. The great flavors, combined with the amazing smoothness, and magical hiding alcohol could provide a troublesome situation for you. And just for a parting word for everyone, while you all have to read this and wait until they are released closer to winter, I think I'm going to go pour myself another and enjoy it on my deck right now. Why? Because...I...can.
More Info:
Share This Page: It will be worth your wait, A Review of Hopslam by Bell's Brewery, Inc.
Hopslam by Bell's Brewery, Inc.
© Copyright 2011-2019 | BrewChief.com | All Rights Reserved


text:
InterContinental Melbourne The Rialto
An iconic
Melbourne experience
Five star Melbourne accommodation in the heart of Melbourne's CBD.
Memorable Melbourne Moments
Uniquely Melbourne inside and out
Elegant and sophisticated, our 253 rooms and suites offer Melbourne accommodation in the perfect CBD location. Each room has been classically interior designed with sleek luxury and a distinctly local flavour. Relax in your room with a range of options such as luxurious marble bathroom with a walk-in shower, spacious vanity area, elegant bedding and a flat screen television with full cable access. Designed for the needs of a leisure guest or a busy business traveller, each room offers high-speed internet connectivity services for up to four devices.
A stay at our iconic address offers a charming combination of elegance, luxury and comfort.
Club InterContinental
From 36 to 52 square meters
Our spacious Club InterContinental Rooms come with exclusive Club InterContinental Lounge access so you can enjoy that extra little bit of luxury, including the benefits of evening drinks and canapes.
From 28 to 123 square meters
Each room has been classically interior designed with sleek luxury and a distinctly local flavour. Relax and enjoy in your room with a range of luxury facilities and features.
IHG® Rewards Club
Earning is effortless. Redeeming points is simple.
InterContinental Melbourne The Rialto is part of IHG (InterContinental Hotels Group) – the world's largest hotel group, with 5,000 properties in nearly 100 countries. IHG rewards guests with a series of loyalty programs, including the world's largest hotel loyalty program, IHG® Rewards Club.


text:
C4 Corvette Parts (1984-1996)
Surprising as it may sound, the earliest C4 Corvettes are over 25 years old! In celebration of this wondrous fact, Zip has loaded up with restoration Corvette parts such as Interior Items Body Weatherstrip Kits, Cooling System Components and more to help keep your late model in peak condition. Of course, we've also included an exciting array of interior, exterior, underhood styling enhancements, performance bolt-ons and exhaust upgrades for 1984-1996 Corvettes. Be sure to check back often as we are adding new Corvette parts and accessories all the time.


text:
Glenn Beck, #1 bestselling author and radio host, reveals the cold truth behind the ideology of progressivism and how the tenets of this dangerous belief system are eroding the foundation of this country.Politics is no longer about pointing to a shining city on the hill; it's about promising you a shiny new car for your driveway. The candidate who tells the people what they want to hear is usually the one who wins—no matter the truth. Politicians may be sleazy and spineless, but they're not stupid. They see that the way to win is by first telling people everything that is wrong with the world, and then painting a Utopian vision that they'll create right here on earth, one where no one is ever sick or hungry, jobless, or homeless. All we have to do is surrender our freedom and someone else's wallet and they'll make it happen. And so they continue to lie, and we continue to believe them, and they keep winning elections. The only way to break the cycle is to understand why Americans fall for the deception over and over again. Progressives from both parties exploit us by first pointing out the things we should be afraid of, and then offering us "solutions" to these fears—solutions that always require us to give up our freedoms. In his signature no-holds-barred way, Beck destroys the false promises of Progressivism and asks us: Why do we accept the lies?
Glenn Beck, the nationally syndicated radio host and founder of TheBlaze television network, has written thirteen #1 bestselling books and is one of the few authors in history to have had #1 national bestsellers in the fiction, nonfiction, self-help, and children's picture book genres. His recent fiction works include the thrillers Agenda 21, The Overton Window, and its sequel, The Eye of Moloch; his many nonfiction titles include Conform, Miracles and Massacres, Control, and Being George Washington. For more information about Glenn Beck, his books, and TheBlaze television network, visit GlennBeck.com and TheBlaze.com.
Browse Related Books
Any use of an author photo must include its respective photo credit
Plus, receive recommendations and exclusive offers on all of your favorite books and authors from Simon & Schuster.
By clicking 'Sign me up' I acknowledge that I have read and agree to the privacy policy and terms of use. Free eBook offer available to NEW CA subscribers only. Offer redeemable at Simon & Schuster's ebook fulfillment partner. Must redeem within 90 days. See full terms and conditions and this month's choices.
Tell us what you like, so we can send you books you'll love.


text:
Thursday, 25 September 2014
Landmark shale gas study shows no groundwater problems
One of the difficulties in the current shale gas debate is that good data is hard to come by. Operators collect lots of data from around their sites, including water sampling to test for pollution, and geophysical monitoring to track where the fractures went during stimulation. However, this data is often considered commercially sensitive, so it rarely sees the light of day.
A government-sponsored project would be very useful, because it would provide a test-bed for an extensive monitoring program. All data could then be made public, and the claims of all those involved in the shale gas debate openly tested.
This is exactly what has been happened in the USA, with the final report released this week. The US National Energy Technology Lab (NETL) sponsored a monitoring program at a hydraulic fracking operation in Greene County, Pennsylvania. The monitoring program consisted of 2 parts: microseismic monitoring to track the fractures created by the stimulation, and geochemical sampling in overlying layers to test whether any contamination has occurred. Most importantly, because the data is publicly available, it's a great opportunity to talk through the anatomy of hydraulic stimulation.
The first stage of shale gas extraction is to drill horizontal wells through which the fracking will be done. The figure below shows a map of the lateral wells drilled. Those in the yellow box were the 6 wells that made up the NETL study.
The figure below shows a stratigraphic column of the geology in the study area. The Marcellus shale is at a depth of 8,000 feet. Overlying the Marcellus at a depth of 2,000-4,500 feet are Upper Devonian age rocks that contain conventional natural gas reservoirs. These reservoirs have been exploited for conventional gas, so wells penetrating these formations are available, and have been used for geochemical monitoring. Freshwater aquifers are found at depths of less than 1,000ft.
I've heard over and over again that apparently shale rocks in the USA don't have faults in them (one controversial geologist in particular springs to mind). Seismic reflection surveys show clearly that the Marcellus rocks in this area are in fact substantially faulted.
I'll cover the geochemical aspect of the monitoring program first. Geochemical tracers were injected with the hydraulic fracturing fluids. Fluid samples were taken from the overlying Upper Devonian layers, and analysed to look for the presence of these tracers, which would indicate upwards fluid migration via natural and/or hydraulic fractures. The figure below shows the monitoring well depths in relation to the shale gas operation.
I won't go into detail on the geochemical evidence, suffice to say that no evidence for upward migration of gas and/or fracking fluid was found. This concurs with the study discussed in my last post: there is no evidence that fluids can migrate from 2km down to the surface - if contamination is occurring, it occurs via faulty well bores, not through fractures in the rock.
Of more interest to me is the microseismic data, because it allows us to see what hydraulic fracture stimulation looks like. Geophones were placed in the monitoring wells that extend to depths close to the reservoir. These pick up the "microseismic events" - the pops and cracks as the fractures open up, allowing us to track where the fractures have gone.
The figure below shows the resulting microseismic map. Each blue dot represent a microseismic event - we can connect them together to see where the hydraulic stimulation fractured the rock.
The first aspect to note is that all the events are close to the well. The hydraulic fractures rarely extend more than 200-300m from the well, and we can see that to be the case here.
Microseismic event magnitudes range between -3.0 to -0.5. This is a typical range for hydraulic stimulation, and is below what could be detected even with a seismometer placed on the surface, and orders of magnitude below what people can typically feel, which is approximately magnitude 2.0.
This is interesting, because as we have seen from the reflection seismic, the rocks here are faulted. We constantly hear about how fracking in faulted rocks will inevitably lead to large earthquakes, water contamination and not much short of the end of the world. In fact, it is rare for a fault to be critically stressed such that it will trigger large events. Service providers have estimated that they see evidence for fracture-fault interaction in about 30% of stimulations, yet induced seismicity such as that seen during Cuadrilla's operations at Preese Hall are very very rare (with 1 case in the UK, and 3 cases in North America).
You can see from the microseismic that one of the stimulations did interact with one of the faults. It can be seen in the cluster of events to the left of the above figure. The figure below shows the microseismic events in more detail, and the fault interaction can be seen in the red-coloured events to the top left.
The next plot shows the same events in a map view. You can see how the events line up to demarcate the re-activated fault.
In summary - I often hear how the faulted UK geology will render hydraulic stimulation impossibly dangerous in the UK, whether because it will trigger large earthquakes or contaminate water supplies. This report shows hydraulic stimulation in the Marcellus shale, with lots of faults in evidence. The microseismic data shows that the fractures interacted with the faults. However, no large seismic events were triggered, and extensive geochemical monitoring showed no evidence of fluid and/or gas migration into shallow layers.
3 comments:
- Anonymous25 September 2014 at 13:15
Certainly very interesting, though one has to bear in mind that it is a sample-size of 1 site out of many sites in the US, and geology and faulting is likely to vary.ReplyDelete
Induced seismicity such as seen in at Preese Hall may be very rare in the US as a % of the many fracked sites there, but in the UK though rare - it is a very high % of the extremely few sites high-volume-fracked so far in the UK, the geology is different here, and so surely we have to take care not to extrapolate too much from that one site to here in the UK.
If fracking happens again in the UK - will you be monitoring and publishing the micro-seismicity for public scrutiny as how was done above?
Your Vertical Depth diagram contrasts with the BBC's weasel 'not-to-scale' "explanatory graphic" that conveniently fails to mention any depths whatsoever.ReplyDelete
Thanks for sharing this post it's very helpful. Great advice for home remedies. We are into the same business for home remedies for indigestion problem, Gas Problem, indigestion relief, bloating remedies and irritable bowel syndrome symptoms. Thank you for sharing the story.


text:
This first post (of a two-part series) about my travels during my term on the Walt Disney World Moms Panel covers the first year of my tenure. Stay tuned to find out about sailing with Mickey on Disney Cruise Line!
The Walt Disney World Moms Panel has become the ultimate experience for Disney fans who want to share pixie dust with other guests by answering vacation planning questions on www.DisneyWorldMoms.com. As a glorious by-product, these Mouse-loving moms and dads also get to do a good bit of traveling to Disney parks, resorts, ships and destinations in order to attend press events, produce videos and commercials and make public appearances. Plus, they also use any and every excuse in the book to see each other as well as meet up at their "happy place."
For me, my journey began a little over two years ago, as I traveled to Walt Disney World for the first time by myself. Our training week was fantastic as our group was treated to special VIP access to attractions, venues, experiences and even a tour of the Utilidor – the underground "backstage" area of the Magic Kingdom.
Shortly after settling back into reality at home, I received a call to request that I represent the panel at the annual Resort Showcase at Walt Disney World. This was an opportunity for media from all over the world to see and experience what was new and next at the parks and resorts, and I was afforded the chance to spend time with two other panelists – Terry from South Carolina and Joanne from Ontario. In addition, a few more panelists were there for the Social Media Moms Conference, and we were invited to a few of their events, too.
After the 22 of us became acquainted at training, we couldn't help but devise a way that we could spend time together again soon. So, in February 2010, several of us from the Southeast met up at Amy Rueffert's restaurant and inn in the mountains of North Georgia for a mini-reunion. Amy's husband, Hans, is a fabulous chef, and it was a chance for our children to meet and become friends, too.
For our family's Spring Break that year, we had already planned for a trip to Disney World and were so excited to meet up with another panelist, Dannee from Indiana, and her family. Each of our kids became fast friends, and we made special memories together that week. Later that spring, my husband was scheduled to attend a business conference at the Yacht Club, so we made plans to enjoy the Pirates & Pals Fireworks Voyage with Marc from New York, Allison from Georgia and Suzannah from Florida. It was amazing how these combined experiences brought us closer together as a group and began to create such a beautiful kaleidoscope of memories for which I now treasure.
Rumors started over the summer that many of the Moms Panelists were going to run in the Halloween 5K or the Wine & Dine ½ Marathon the weekend of our Disney Moms Panel Reunion in October. I quickly brushed off the offers with my usual, "I don't run." Then, with a little encouragement (and a few challenges) from my fellow panelists and family members, I reluctantly agreed. I did it all in the name of Give Kids the World – a local Orlando charity which provides amazing vacations for chronically ill children and their families. Yet, it's what kicked me into gear, and I haven't stopped running yet. (Since I'm from Alabama, you can insert a visual of 'Forrest Gump' here.)
Upon my return from the Moms Panel Reunion Weekend, I came home for one day and was back on a plane the next traveling to the Latina Media Week showcasing Walt Disney World Parks and Resorts to Hispanic travel writers and bloggers from the US and Mexico. Like always, the Public Relations Team at Walt Disney World scheduled incredible experiences, delectable dining and basically just showed off! We were treated to a rare, behind-the-scenes peak into the Holiday Services Department and even got to take home a souvenir ornament. I met such wonderful people and made life-long friends. It was like training week again, but I served as a hostess instead of a guest – providing tours and information and giving the writers story and photo ideas tailored to their readers. Carol (NYCityMama.com) and Sylvia (DisneyLandiaalDia.com) were two of my mommy blogger friends I made that week and still keep in touch with. I loved showing them my Disney World!
In November during our Thanksgiving break, I snuck over to Atlanta with three of my kids one day to spend some time with one of my dearest friends on the panel, Allison. She and I have become so close that we sort of have developed our own language, and it's been incredibly enriching to have her in my life. Our families have become close, and she is the greatest "swag" I've ever received from being a member of the Walt Disney World Moms Panel.
To cap off 2010, my family and I scheduled my Disney Moms Panel reward trip for the week in which our Alabama Crimson Tide was playing in the Capitol One Bowl in Orlando. We enjoyed a week of visiting the parks but also loved the entertainment and recreation opportunities throughout the property that we don't normally take the time to do – DisneyQuest, mini-golf at Winter Summerland and Fantasia Gardens and Typhoon Lagoon Water Park. The time at Walt Disney World during the holidays also allowed me the chance to catch up with a few more panelists including some "newbies" who had just been through training in preparation for the 2011 term. My family and I actually rung in the New Year watching the most amazing spectacle of fireworks at the Magic Kingdom to fittingly symbolize the mind-blowing year we would experience in 2011.
Although I am a member of the Walt Disney World Moms Panel, my opinions do not represent Disney, and I received a week's vacation for my family and me at the Walt Disney World
Resort in Florida for my 2010 term on the panel.


text:
Usually when I bake with my four year old I spend a lot of time reminding him not to stick his fingers in the mixture, not to lick the spoon while in the middle of mixing, and not to taste every ingredient as it goes in, but today was different.
Today we made gingerbread cupcakes and I let Noah taste test at every stage!
Usually you only get to taste the finished product, or maybe a quick taste of the mixture before it is baked, but there is a lot to be learned from tasting each ingredient as you add them!
So, armed with a drink of water and a special tasting spoon, we started by combining the dry ingredients and dipping a finger into each one to try a little.
It was funny to see his face screw up when he expected the flour to be sweet, and his eyes grow wide as he tasted each of the spices. He said the flour 'tastes like nothing', pronounced the cinnamon and allspice to be 'hot' and the ginger 'yum but strange'.
We didn't need to taste the butter as he already knows what that tastes like, but he couldn't resist a little try of the brown sugar. He was interested in the molasses as it is sweet, but not as sweet as the sugar, and he wasn't keen to try the raw egg.
We mixed the butter and sugars with the electric mixers and Noah was interested to see the ingredients change as they combined. We mixed the dry and wet ingredients and filled up our cupcake cases and then it was time to lick the spoon!
Noah was amazed that even the 'yuck' things tasted good when we mixed them all together! And that is the magic of cooking!
If you'd like to make your own gingerbread cupcakes, there is the recipe:
- 1 cup of plain flour
- 1/4 tsp baking soda
- 1 tsp powdered ginger
- 1/2 tsp cinnamon
- 1/2 tsp allspice
- 90 gm butter, softened
- 1/2 cup brown sugar
- 2 tbsp molasses, golden syrup or treacle
- 1/4 tsp vanilla
- 1 egg
- 1/4 cup milk
- Preheat the oven to 180 Celsius and line a muffin tin with cupcake cases.
- Combine the flour, baking soda and spices and mix well.
- In a separate bowl beat the butter and sugar until light and fluffy, add the molasses and mix well.
- Add the egg, vanilla and milk and mix for a few minutes until well combined.
- Add the dry ingredients to the wet and mix well.
- Spoon the mixture into the cupcake cases until they are 3/4s full and bake in the oven for 20- 30 minutes or until the cupcakes are springy to the touch.
Because these are gingerbread, and cousin to gingerbread men, we added simple faces to our cupcakes using smarties glued on with icing for eyes, and simple icing mouths and eye balls!
And the best part of the taste testing was eating the finished product! Yum!
For more Christmassy 'taste' activities check out these great posts:
Christie from Childhood 101 has some cool stained glass cookies.
Cathy from Nurture Store has some fabulous gluten and egg free Peppermint Creams.
Ana from Babble Dabble Do has some delicious Mexican Hot chocolate.
Meri from Meri Cherry has some incredible lickable holiday wallpaper!
Kristina from Toddler Approved has these gorgeous 'build a snowman' Cookies!


text:
NTPC Limited (up 0.7% at Rs 161.10) has announced that the second unit of 660 MWof Mouda Super Thermal Power Station Stage-II (2 X 660 MW) has been commissioned. With this, the commissioned capacity of Mouda Super Thermal Power Station, NTPC and NTPC group has become 2320 MW, 41907 MW and 48873 MW respectively.
On Saturday (March 18), NTPC had announced the commissioning of the 25 MW of Bhadla Solar Power Project. With this, the installed capacity of Bhadla Solar Power project increased to 185 MW and that of NTPC's solar power projects rose to 545 MW.
The company posted a net profit of Rs 2468.72 crore in the quarter ended December 31, 2016 as compared to Rs 2668.77 crore in the December 2015 quarter. Total income increased from Rs 17,724.68 crore for the quarter ended December 31, 2015 to Rs 19,646.09 crore for the quarter ended December 31, 2016.
The stock had touched a high of Rs 177.80 in the last week of January 2017. The stock was trading around Rs 125 in early April 2016.
Investors looking at medium or long term can go in for NTPC at current levels and consider adding more at declines. The stock may stay a bit sluggish in the near term, but modest upside from current levels is not ruled out.


text:
- Description
The GFK-4 Temperature Controlled 165 CFM Fireplace Blower Fan Kit with Speed Control Knob by Skytech is designed to circulate warm air through many hearth products in the industry, and provide variable speed control with a manual control knob; specifically, it is a replacement for the Heatilator GFK-4 Fan Kit. This unit operates on 120VAC, 60 Hz power, and increases the amount of air the fan will circulate through your fireplace or stove to 165 CFM (Cubic Feet per Minute). The increase in circulation allows the room temperature to heat more quickly, and maintain a consistent temperature - which also improves the energy efficiency of your appliance, and help you save on energy costs. The blower fan will automatically turn on when the temperature sensor reaches 110°F and will turn off when the temperature drops below 90°F. Increase the circulation of heat created by your appliance, and improve the energy efficiency in your home.
- Manual speed control for fan
- Sealed bearing construction for noiseless, long-lasting performance
- Anti-Vibration impellors for silent operation, and high quality air-flow
- Easy to install magnetic mounting strips hold the blower in place
- Automatic temperature sensor turns unit on at 110°F and off at 90°F automatically
- High volume 165 CFM (Cubic Feet per Minute) output
- Certified by ETL; Complies with CSA C22.2; UL listing 1004
- Blower Dimensions: 4"H x 12.75"W x 3.5"D
- 2 Year Manufacturer's Warranty
About the Manufacturer:
For decades Skytech has led the hearth industry by producing high quality fireplace remote controls, fan blower kits, and gas valve kits in order to supply the industry with the parts it needs to provide the warmth and comfort of a fireplace for all of us to enjoy. By offering a wide line of products and replacement components, Skytech continues to help keep gas fireplaces running well and providing the heat and comfort we all expect.
- Additional Information
Additional Information
UPC 600165885049 Manufacturer Skytech Shipping Status No Condition New Remote Functions No Screen Type No Fuel Type No Style No
- Reviews
Frequently bought together
Skytech 3301 On/Off Fireplace Remote Control With Timer/Thermostat
Regular Price:
Today's Price
Skytech 1001 On/Off Fireplace Remote Control
Regular Price:
Today's Price
Skytech 1001TH On/Off Fireplace Remote Control With Thermostat
Regular Price:
Today's Price
Skytech 1410 On/Off Fireplace Remote Control
Regular Price:
Today's Price
There are no product questions yet.


text: Judge Carter was appointed in August of 2010. He served as a judge for both the Office of Medicare Hearings and Appeals and SSA before transferring to the NLRB. Before becoming a judge, he worked as: an Assistant United States Attorney in the District of Columbia; a trial attorney in the Civil Rights Division of the Department of Justice; an appellate attorney for the EEOC; and as a law clerk to Judge Diane Wood of the United States Court of Appeals for the Seventh Circuit. He received his B.A. degree, with distinction, from Stanford University (class of 1992), and his J.D. degree from the University of Chicago (class of 1996), where he wrote for the law review.


text:
Cold Cases: Forensic Experts Work to ID Unidentified Crime Victims
There are more than 400 people buried in the Harris County Pauper's Cemetery just outside Houston who've never been identified. Forensic Anthropologists are using state of the art forensic technology to identify some of them, and, it is hoped, figure out how and why they died.
The review centers on cases from the late 1950s to the late 1990s, decades during which Jane and John Doe bodies were buried before collecting and recording DNA samples in national databanks became standard procedures at the county's Institute of Forensic Sciences.
Harris County's forensic anthropology director, Jennifer Love, known as "the Bone Detective," will use a grant from the National Institute of Justice to exhume and identify at least 25 bodies.
The problem of identifying the dead goes far beyond Harris County. Across the country, an estimated 40,000 people are buried but unidentified. That means killers are never brought to justice, and families never learn what happened to their missing loved ones.
This national phenomenon has been dubbed "The Nation's Silent Mass Disaster" by the National Institute of Justice.
via Cold cases: Forensic expert's project could resolve decades-old deaths | Newswatch | a Chron.com blog
Forensic anthropologists are asking the public to help in this investigation. In order to use newly collected DNA samples to restore identities, they're asking relatives of long-lost or missing persons to provide names and DNA samples — which might match samples collected from corpses in the Pauper's Cemetery.


text:
I think we were all caught off guard yesterday when Grouse announced they'd be open for Day 1 of skiing and riding this Saturday. The weather has been cold but pretty dry. It's been cold enough though to make snow and Grouse blew a patch big enough for Marcus Cartwright and his crew to install a park and BOOM! park riding season is on at Grouse Mountain. All the usual suspects plus crews down from Whistler (not open for riding yet), Nuulife, and Footy Fiend turned up and turnt up!
Here are a collection of shots from Day 1. The tricks and faces showing up at Grouse Park. Stay tuned to the blog for more photos and video edits dropping soon!
Grouse Park introduced the North Shore's first concrete feature bringing a real street feel to the park on Day 1 and all the features were fresh out of the shop and as smooth as an A$AP verse.
Grouse Park Crew where on it maintaining as was John Swystum from Nuulife Cinema maintaining behind and in front of the camera.
Firecrackers allowed. So is 'hands in the pockets' steeze.


text:
A special organisation in Morecambe's West End gives hope, support and understanding to families, the homeless and the needy.
West End Impact on Heysham Road, a registered charity, is run in partnership with Morecambe Community Church in response to the regeneration of Morecambe.
Set up in 2002, the charity has grown and expanded and now offers a community cafe, boogie babies, surgeries with PCSOs and Disability Online, a free meal once a week for the homeless, a drop-in service for homeless people, food parcels and most of all care and understanding.
Manager Tracy Kohl said: "Morecambe Community Church and the Impact is where we carry out our work.
"We want to bring regeneration into peoples' lives rather than old buildings.
"We want to help people in this area.
"We did the building on Heysham Road up from scratch and in 2011 both buildings were made into one.
"We are far more than just a homeless project, we always have more plans but more volunteers and resources are needed. We are lacking space already.
"Funding is always difficult to get and we try and hold fundraisers when we can.We have our Impact Angels who donate £10 a month .
"The community cafe charges for food just like any other cafe.
"We have 40 volunteers, some do two hours a month and some do two or three days, but we always need more volunteers.
"There has been a shift recently where people on Job Seekers Allowance for six months have to go on a work programme.
"People get sanctioned and end up completely without money but there is a knock on effect and people could eventually end up homeless.
"The system is completely flawed and people are on the floor and need an advocate.
"There are a lot more middle aged men coming to the centre for help.Mental health is an issue and people with mental health issues are falling through the net.
"The only way to access treatment is through your GP, but we would love to have a GP to do visits with us now and then.
"Beneath the surface my faith keeps me going but it does sometimes get too much.
"With West End Impact I feel a sense of pride and a sense of achievement but there is always more to be done."
Call West End Impact on 01524 888929 for more.


text:
One of the problems of flying model airplanes and quadcopters is that each controller manufacturer uses a propietary protocol, even if all normally will be using the 2.4 Ghz those will be incompatible with each other. But thanks to Deviation firmware is possible to convert a cheap RC transmitter in a machine able to control practically anything that fly.
Deviation is a replacement firmware ( with full open source code) designed primarily for the Walkera Devo series RC Transmitters. While Deviation is heavily influenced both by the previous Walkera DEVO8 firmware as well as by the Flysky/Turnigy based ER9X firmware, it has been written completely from scratch to be easily portable and extensible.
Deviation TX supports multiple protocols. You can turn your affordable Devo transmitter into a power house that supports multiple protocols without any modifications to the transmitter: Walkera, DSM2/DSMX, JR,Spektrum,Turnigy, Orange and Nine Eagles. Add some cheap modules like the common NRF24 modules and you could emulate Turnigy 9X, Hubsan X4, V202, Skyartec, Tactic SLT/Anylink, Hisky transmiters. And thanks to the deviation community the list of supported protocol is always expanding.
Currently supported models includes DEVO 6/6S/8/8S/10. So probably the most asked question on these forums is which Devo TX to buy. There is no one-size-fits-all answer to this, but I will give my personal personal setup here.
The Devo 7e can be had for $60 US. That puts it in the same price range as a Turnigy 9X. Devo 7e is cheap, comfortable size, light weight and has a bright screen. Add a pair of modules for the most common toy quadcopters protocol and you have a do-it-all RC TX under $80.
- Walkera Devo 7E 7CH Transmitter Mode 2 – US$59.59
- NRF24L01 Transmitter Module (Wltoys Protocol) – US$7.99
- A7105 Modification Module (Galee Flysky Protocol) – US$8.59
People at deviation forums has published all you need from Transmitter Setup Guides, How to Videos, and Models for Deviation Firmware. http://deviationtx.com/forum/how-to
DeviationTX install
NRF24L01 Module install


text:
Clif Bar recalls its Clif Builders Chocolate Mint Protein Bar because of undeclared peanuts and nuts and incorrect allergen labelling
Clif Bar is recalling its Builders Chocolate Mint Protein Bar as it may contain peanuts and nuts not mentioned on the label, and barley, rye, wheat and milk not correctly declared. This means it's a possible health risk for anyone with an allergy to peanuts and/or nuts, and an allergy or intolerance to some cereals containing gluten (barley, rye, wheat), and/or milk or milk constituents.
Follow the link for more detail.


text:
Collecta Shuts Down Its Real-Time Search Engine
Collecta, one of several search engines that aimed to make the growing amount of real-time data searchable, appears to have formally shut its doors.
A message on Collecta's home page tells visitors, "The Collecta story will be updated shortly … you caught us in transition." ReadWriteWeb reported earlier that Collecta plans to make its software open source and is already working with agencies such as the United Nations that could potentially use the software to help with crisis relief projects.
Collecta launched about two years ago when real-time search was a hot topic. It offered a number of advanced search options and claimed to have information available to users less than a second after it appeared on Twitter, Flickr, blogs and other sources.
In January of this year, Collecta effectively left the real-time search space and said it would take a step back to assess its future. At that time, Collecta CEO Gerry Campbell told us that the real-time search market didn't develop in the way the company had hoped.
Erstwhile Collecta competitors Crowdeye and OneRiot have also gotten out of the pure real-time search space.
We're listening.
Have something to say about this article? Share it with us on Facebook, Twitter or our LinkedIn Group.


text:
Dual seat adjustments, a large comfortable seat and easy entry make the ISO7000 ideal for users of all sizes. Features of the ISO7000 Upright Bike include:
- Vertically and horizontally adjustable seat ensures an optimal biomechanical fit for a broad range of heights.
- Oversized seat provides comfort for all users.
- Step through access allows entry without lifting the leg over center support.
The ISO700 Upright Bike l is a great investment for residential and commercial gyms alike!
View more offers from this member
ISO 7000 Upright Bike from SCIFIT
This Member has requested that you contact their representative about all Exchange
work. Reasons for this may include limited supply, seasonal availability, pre-qualification
of work or other limiting circumstances that may prevent them from taking all Bizx
To learn more and to request a purchasing opportunity from this company, please
Shipping charges are in cash.
TradeX Version:2019-01


text:
Braithwaite & Co. Ltd. recruitment 2016-17 notification Secretary Posts: Braithwaite & Co. Ltd. Invites application for the post of Assistant Company Secretary.
Advertisement Number:- Rectt./2016/4
Braithwaite & Co. Ltd. Jobs 2017 hiring Details:
|Organization Name
|Braithwaite & Co. Ltd.
|Name of Post
|Assistant Company Secretary
|No of Post
|01 Posts
|Last date to apply
|25th October 2016
|Job Location
|Kolkata (West Bengal)
Braithwaite & Co. Ltd. free job alert 2017 vacancies information
Name of Post:- Assistant Company Secretary
- Total no. of Posts:- 01 Posts
- Age Limit:- 45 years as on 1st January 2016
- Pay Scale:- Rs. 29100 – 54500/- Per Month
- Qualification:- Graduate in any discipline.
How to apply offline for Braithwaite & Co. Ltd. exam 2017:- Interested and Eligible candidates may apply in Plain Paper with detailed Resume, Photograph and copies of certificates/ documents send to Sr. Manager (P,A,S), Braithwaite & Co. Ltd., Hide Road, Kokata – 700043 on or before 25th October 2016.
Important Dates:-
Closing / Last Date for submission of application: 25th October 2016