Finding the height of any point on a 2d plane perturbed by a sine wave

AKA: Making water waves

I wanted to make a special effect for some software that I’m writing. It involved simulating waves in water inside the vertex and fragment shader in an OpenGL program.

While I found a lot of posts on the subject, none of them worked from the ground up to explain what was going on with the math (mostly trig) in the calculations. Since I work a lot better when I can see examples visually, I wanted to share my thoughts while I was going about the process of understanding what I was reading in my head.

There wasn’t a whole lot as far as code because much of it is hidden behind vector operations like the dot product, but really digging down I found the methods interesting nonetheless. I hope my brain dump can make other people excited about some of the stuff behind 3d.

 

There are many ways to look at a sine wave. Most people know it as the uppity downity regular pattern associated with waves of all kinds. I like to look at it depicted as a continuous revolution around a circle being drawn by a marker.

Sine wave amplitude being drawn from the Y component of a rotation around a circle.

One sine wave is completed each time we go all the way around the circle. This means that as we input between 0 and 2*PI radians into the sin() function, we complete one whole wave. Once we go over 2*PI radians, the function starts over. Another way of saying this is that the domain of sine is between -1 and 1: No matter what goes in, something between those numbers comes out.

Lets say we want to create one of these waves “traveling” in some two dimensional direction given a change in time. We then want to render that traveling wave on a computer screen. We also want to be able to control the frequency of the wave. How many peaks and troughs we’ll see given a single span of 1 unit.

As shown above, we know to complete a full wave we need to input 2pi to the sin function. Therefore, we should multiply our desired frequency by 2pi.

float frequency = 2*pi * desiredFrequency;

You can think of this mutiplication as creating a situation where we pass in the same X value of 2, but more waves have been generated by that point.

Screen Shot 2015-03-06 at 6.34.41 PM

Multiplying by frequency

Since the sine wave is going in a certain direction, the last thing we need to know to draw a point on our plane is how much the position of the point is contributing to amount traveled along the wave.

We can figure this out by obtaining the dot product between the direction the sine wave is traveling, and the location of the point which is itself a vector rooted at the origin.

Screen Shot 2015-03-06 at 6.43.41 PM

 

Remember that the dot product tells us the cosine of the angle between point vector from the origin and the wave direction. Cosine according to SOH CAH TOA is the ratio of the adjacent side of the triangle vs the hypotenuse. This is exactly the ratio we need to determine how much of the magnitude of the point contributes itself in the direction of the wave.

Putting this together in code, we get:

float theta = dot(waveDirection, vec2(x, y));

Theta is then how much x, y point/vector has moved us along the wave.

Now, finally, we can calculate the height of the wave at the given X,Y point.

//inputs are:
//vec2 waveDirection: The direction the wave is traveling
//float freq: The number of complete waves per unit distance
//float amplitudeMul: The amplitude multiplier for this wave
//float time: input time to create wave movement
//float x: X coordinate of the point we're drawing
//float y: Y coordinate of the point we're drawing

float wave(vec2 waveDirection, float freq, float amplitudeMul, 
    float time, float x, float y) {

    float frequency = 2*pi * freq;
    float theta = dot(waveDirection, vec2(x, y));
    return amplitudeMul * sin(theta * frequency + time);
}

Happy waves!

The choice is yours

The choice is yours

The beginning and the problem

That’s me, the little dude on the right wearing the leg brace. My sister is sitting next to me on the left and we’re both on my father’s lap. My father was so proud of his little boy even with the minor physical glitches that he came with. My father never told me there would be things that I couldn’t do. The doctors did sometimes, but because my parents supported me, I really didn’t listen anyways. My parents told me I could be anything. My parents were right.

I was born with a pretty severe case of club foot. My left and right legs needed a lot of work when I was a child. I still have limited rotation in my ankle, and my left kneecap is malformed which creates all kinds of interesting flexibility problems.

The only way you’d know this today is by the slight limp in my every step while I run the 5k right next to you.

I never gave up and I never settled, but that doesn’t mean there weren’t rough spots along the way.

A larger version of me

A different version of me

This was me a few years ago. I had stopped caring what I looked like for a bunch of reasons, ate what I wanted, and gained a lot of weight. I was right around 230 lbs at 5’10” and not healthy at all.

I lost my father to heart disease and the problem got worse. I began experiencing heart rhythm issues that stole my ability to think about anything but what I thought was my impending death. When I finally was able to overcome my fear and the arrhythmia became less frequent, I thought again about my father. I thought about how he died so young in modern terms, at only 60 years old. I decided that I wanted to live longer than this. I’ve always felt like I have a lot to do here and that to accomplish my dreams and to pass them on, I need all the time that I can get.

Me now

A shot of me now while visiting a friend in Seattle

Long workout routines at home, eating right, and then finally joining a gym and I was able to get the weight off. I feel a whole lot better than I did, and I learned a few tricks along the way that helped to get and keep me where I am. All total so far over the past few years, I’ve lost 55 lbs. I now weigh 175 lbs and am hovering just above 10% body fat.

If you’re struggling with your weight, you are not alone. It is a tough road to travel, it is not easy to change your eating habits, it is not easy to want to work out, and the results mostly do NOT come fast. Anyone telling you they do is trying to sell you something. But if the little boy up there with the braces on his legs can do it, you can too.

Never thought I'd see myself like this

Never thought I’d see myself like this

It’s your time. Do it and mean it.

If you’ve been thinking about leading a healthier lifestyle, there is no better time to start than right now. You will feel better, you’ll have more energy, you will get sick less often, and over the long term you will have less health issues. The work you put in every day will pay off in more ways that I can even bother to try to convince you of. Based on my experience, I promise you the benefits far outweigh the sacrifice.

I want to share you with a few things I learned over these last few years. These things have helped me to keep up with my exercise routines even when I am beyond exhaustion, and have helped me to eat right even when I’d rather be grabbing a hamburger sandwiched between two donuts.

Set goals for yourself, but make them realistic

You need to know WHY you are working out in the first place. Look online for information about weight loss and set realistic monthly goals for yourself. Don’t beat yourself up if you don’t hit them, but use that as a motivation to work harder.

Make exercise a habit

Push yourself to stay on a routine for a long enough time that you feel emotionally bad when you can’t go. This takes a few months in my experience. Once you have that, the need for extra motivation isn’t as great. You will want to go and will get frustrated when you can’t. This makes it less likely you’ll skip for stupid reasons.

Distract yourself and push past into your second wind

When all your muscles are burning, and your chest is on fire, you may literally feel like you’re “going to die”. The biggest gains come when you push past that. Distract yourself. Think about something else. Be somewhere else to push past it. The worst thing you can do when your legs are burning while doing a 2 minute wall sit is think about your legs burning.

Find people that will help, not hinder your progress

If you’re going to work out with a friend or friends, do not choose people who will be prone to try and talk you out of going to the gym or exercising for various reasons on the day of. I see this all the time with groups that decide to do something like go have coffee instead of working out due to the smallest, silliest things. For example, one person is tired and convinces everyone else to quit. Avoid these people, or if you’re the kind of person that can motivate them instead, do it. Either way, if they don’t want to work out, you have to force yourself to do it without them. Don’t get sucked into the lazy trap. Find people that will challenge you and create positive group think.

Change up your workout

Your mind will bore of the same routine day in and day out, and your body will get used to it to the point where it provides no benefit. Change it up. Do different exercises. Add more weight. Run faster. Increase the incline on your treadmill. Pull up the resistance on your exercise bike. CHANGE IT UP!

If you can, go to the gym or somewhere outside of your house to exercise

I used to work out at home, and though I made huge progress on my own in the beginning, eventually I fell off. If you find yourself in this predicament, your best bet is to go to a gym. You change your surroundings, you have less opportunity to get distracted, and there is far more equipment there to use. You are also in a social environment and may meet friends to help you along your way.

If you can afford a trainer even for only 4 sessions, do it

Personal trainers can be expensive, but the best thing they provide in my opinion is customized routines. If you can afford to get a trainer for a month once a week, do it. Have the trainer build you multiple exercise routines that you can use even after the sessions have expired, and pay attention to the exercises they make you do.

Eating right

One of the things I talked to healthy people about is diets. It takes a combination of diet and exercise to achieve extreme results. I’ve chosen a modified paleo style diet, but one thing that all the modern meal plans seem to have in common is eating far less carbohydrates and refined sugars. Skip the breads, the tortillas, the pasta. I’ve personally found my mind to be much clearer and my energy levels much higher without them. Don’t be afraid of fats (especially unsaturated), there is a lot of evidence out there right now indicating they are not the evil creatures they have been made out to be. Eat a lot of protein, you’ll need it to recover.

Stop eating massive amounts of sugar. This means kicking the soda habit. Where you need something sweetened, look to natural sweeteners like stevia, or naturally occurring sugar alcohols like xylitol, and erythritol. These can even be used in almond and coconut flour to make modified baked goods!

I hope what I’ve written can help some of you who are on the fence about this stuff and help you to stick with a routine once you’ve started. I also hope that once our InShape project is up and running in the next few weeks you’ll join me there on virtual runs in the mornings. I’d love to have more friends while I’m staying fit!

Good luck. You can do it!

Homemade sugar free cranberry soda

Homemade sugar free cranberry soda

We had a taste for something to drink besides plain and sparkling water. Being totally adverse to just about anything with added sugar nowadays, I wanted to see if there was a way to sweeten up cranberry juice without drinking up a ton of carbs.

I didn’t think stevia would work because it has a naturally bitter aftertaste just like cranberries, but to my shock and surprise my first experiment was a success! A bit of tweaking the formula and I came up with a decent cranberry soda which I share here with you!

Sugar free cranberry soda

  • 1/4 cup 100% pure unsweetened cranberry juice (preferably not from concentrate)
  • 1/4 tsp pure stevia extract
  • (optional) A pinch of another sweetener like xylitol or erythritol
  • Sparkling water/soda water (a sodastream works great for this)

Pour the 1/4 cup cranberry juice into a 16 oz glass. Add the stevia and optional pinch of other sweetener to the juice in the glass and stir until completely dissolved. Slowly add the soda water.

That’s it! This recipe yields a nice solid soda flavor and in my opinion there isn’t even a hint of bitterness from the stevia.

Reality check on opensim stats

As I suspected would happen, a recent article on hypergrid business has people speculating that the opensim metaverse is crowding out and outgrowing commercial grids and will now all of a sudden take off without them.

So I did some fact finding and found something very interesting.

There has indeed been growth in opensim grids over the past 3 years, but it has been dismally small. Until people come to terms with this and start advertising their grids (be them free or commercial) this trend will continue. Of the growth that has occurred since 2011, the majority of it has happened on the back of InWorldz.

Using the statistics provided to me by Maria Korolov, I tracked total active user growth for all known opensim grids between December 2011 and December 2014. Are you ready for this?

Total opensim active users growth 2011-2014:

  • 5,043 users (yuck. for comparison over 7700 people have purchased minecraft in the past 24 hours)

Total InWorldz active users growth 2011-2014:

  • 2,803 or about 56% of the total for all new active users

If I go back to our peak a few months ago of over 8300 active users, we account for an even larger percentage.

I understand there are many out there that for one reason or another don’t like InWorldz, but between our continuing small marketing pushes on facebook, and our largest advertising campaign ever coming in the next few weeks, we contribute to a great degree to the inflow of new users to the opensim platform. Our servers and staff have taken care of over 100,000 registered users and we have a lot of lessons learned because of it, which we’re sharing as we can. Starting more infighting over dismal numbers isn’t going to grow the opensim VR space.

CentOS 7/RHEL 7 and docker containers on boot

I recently had to work with a CentOS 7 system and a few docker containers. These containers were bound to different IP addresses on the server NIC and it was critical that they be available after a server reboot. CentOS 7 comes with docker 1.3.2 built into the base installation. This version supports the –restart switch as follows:

–restart=”” Restart policy to apply when a container exits (no, on-failure[:max-retry], always)

Setting the containers to restart=always, rebooting the box, and running docker ps, I discovered that the docker containers were not starting with the OS. After going through a few combinations of commands unsuccessfully I decided to take a look at the message log for the system and I noticed something odd:

Received an unexpected error during port allocation: Error starting userland proxy: listen … cannot assign requested address

Taking a closer look at the logs I noted that this was often followed later by something like:

kernel: e1000e: enp0s25 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: Rx/Tx

It looks like the docker container engine was starting before the NIC was actually up. It was then trying to do its magic and create the bridge interface but the NIC with the given IP address wasn’t ready yet.

To solve this issue I looked around and found an article about systemd services specifically dealing with depending on the network interface to be up. Inside the systemd unit for docker, the service was set to depend on network.target:

/usr/lib/systemd/system/docker.service:

[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=network.target docker.socket
Requires=docker.socket
Wants=network.target

Additionally, /usr/lib/systemd/system/docker.socket was not set to depend on network.target at all. To get everything rebooting with the system, I did the following:

  • Added network-online.target to the Requires and Wants of both the docker.service unit and the docker.socket unit.
  • Ran
    systemctl enable NetworkManager-wait-online.service

    to stop boot processing until the network is available.

Both of these steps may not have been needed and you should play around with the configuration to see what works for you. My final .service and socket files were as follows:
[ddaeschler@docker ~]$ cat /usr/lib/systemd/system/docker.socket

[Unit]
Description=Docker Socket for the API
PartOf=docker.service
After=network-online.target
Wants=network-online.target

[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target

[ddaeschler@docker ~]$ cat /usr/lib/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=network-online.target docker.socket
Requires=docker.socket
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
ExecStart=/usr/bin/docker -d $OPTIONS $DOCKER_STORAGE_OPTIONS
LimitNOFILE=1048576
LimitNPROC=1048576
MountFlags=private

[Install]
WantedBy=multi-user.target

After making these changes, the containers start up normally at boot. I hope this can help someone else running into this issue.

Xcode handy key bindings

This is a tiny postlet on some key combinations I have found handy while using Xcode. I’ll update this as I run into more invaluable shortcuts.

  • shift + cmd + o - Quickly open file
  • shift + cmd + j – Reveal in project navigator
  • ctrl + cmd + up / down – Jump to next counterpart (ex. .h/.cpp file)

A ton more are listed here: http://nshipster.com/xcode-key-bindings-and-gestures/

Relay for Life on InShape!

Relay for Life on InShape!

On November 1st 2014, something profound is going to happen, and I’m super excited to be a part of it.

For the first time, avatars and the people behind them are going to run the American Cancer Society Relay for Life, for real, virtually.

What in the world does that mean?

RFL_Snapshot_001Using the InWorldz InShape system, beta testers from the virtual world will get together on a virtual track that has been designed by Relay For Life of InWorldz volunteers. They will log into the virtual world, and by using acceleration data supplied by the cell phone in their pockets, they will transmit walking, biking, and running forces from their real life into their avatar. That data will be used to move them through the Relay for Life track.

From exercise bikes, to rowers, to treadmills, the harder they run in real life, the faster their avatar will go. Their dedication will show through form the real to the virtual. Their avatar will become an extension of the good we all want to see in the world.

Business stamina

We will gather from around the world. We will run the same track for the same great cause, and we will help to give hope where hope is needed.

This is what virtual worlds are all about. Fighting for good causes and using virtual worlds technology to augment the human experience. If you are an InShape beta tester, please join me on November 1st to help kick cancer right in the backside. Let’s get together and sweat to draw attention to a disease that affects us all, and needs to be eradicated before it can claim any more lives.

Run for life.

(Watch the livestream here starting at 9 AM PDT)