Skip navigation

https://www.facebook.com/search/me/friends

 

If you’re having a problem compiling with an imported project check:

  1. The path of the engine in the .vcxproj
  2. Visual Studio version (VS 2013 project doesn’t work well under VS 2015, try and upgrade)

Code Compare. This is exactly the tool I was looking for.

codeCompare

It reminds me of a modern version of Windiff.exe. With handy widgets for copying left and right (which WinMerge does not supply), this tool is well worth the $49.95 licensing cost (but a lower one-time purchase price of just $20 may be better).

 

Getting a hang of Microsoft Word styles can be difficult. Here are a couple of issues solved.

Font of a Style overriding main document style

The font used in a word for a style is actually located under Font, and it DOESN’T have to be the name of a font. It can be +Body or +Heading if you wish, to use the default body or heading fonts. Simply choose one of the top two items in the dropdown list (defaults Cambria (Headings), Calibri (Body)) to use the default fonts for the document. Alternatively if you go into the drop down in the lower left corner and select Format / Font.., you can choose either +Body or +Headings to use the Body and Headings default fonts respectively:

font-sel

To change the DOCUMENT’s default fonts, you have to go to the Design tab in the Ribbon, and select the Fonts dropdown to the right of the Themes listing.

document-font-sel

1. Casting a spell is an expression. All you have to do is express what you want. You can use pictures, feelings, anything.
A spell is the feeling of it.
It’s best to picture the end result of the spell, that way the pathway to make it happen is automatically figured out and it leaves less room for someone else to interfere with the spell. For example, if I want to have a nail in a wall, rather than picture the nail in smoothly, I should picture JUST the end part, where the nail IS in smoothly. This clearly expresses what I want with no ambiguity and no room for someone else to interfere with the spell, which they may do to cause it to fail.

2. Your subliminal wants emerge in your world. You are continually casting magic by your wants and desires.

A subtle trapping is to be harmed by fearing something so much that you just want it to get over it. For example, if you’re hammering a nail, you might fear hitting your thumb so badly that you “want” to hit it, just to avoid having to fear it any longer.

This sentiment can kill you however. To avoid feeling it, really think about what the bad outcome means, and what would happen if you DID hit your thumb.

Arc length is just:

L = rθ

Verify this by acknowledging

C = 2πr

In that case, θ = 2π

4d space is simply overlapping 3d volumes.

each dimension you add multiplies the previous dimension by infinitely many of the previous “type” of object.

For example:
0d: a point.
1d: a 1d line, or infinite stack of parallel 0d points
2d: a 2d plane, or infinite stack of parallel 1d lines
3d: a 3d volume, or infinite stack of parallel 2d planes
4d: 4d space, or “infinite stack” of parallel 3d volumes

parallel 3d volumes may seem hard to visualize, until you realize that they are just overlapping 3d spaces.

if you know computer graphics, think of rendering the same thing twice in the same spot. for example, a character, once with normal skin and once with werewolf skin. the second render introduces a “4th dimension” or a “parallel reality” for the character. if both renders are supposed to represent the same character, and these impassible objects can overlap, then we are now talking about parallel 3d spaces (since overlap of solid objects should not be possible in a single 3d space). the character now appears in 4d space, where he experiences the “parallel realities” of both being “normal” and “werewolf skinned” at the same time.

There’s an odd quirk in PowerPoint 2016 that causes the Text node in the Slide Master to not show up in the children.

  1. Insert Slide Master
  2. Move the text in the MASTER SLIDE off to the right, so you can clearly see which ones it is has skewed in of the LAYOUTS that are automatically set up below.
  3. Delete all the template layouts so you just have the Slide Master EXCEPT the 2nd Layout that has the movable Content node.
  4. You can duplicate this Layout node for additional nodes that have linked Content to the Master node.

linked-master-content

This is the only Layout whose Content node modes with the Text in the Master. It’s difficult to get Powerpoint to behave this way otherwise.

By default, PowerPoint cleans up (by deletion) all unused master slide layouts almost immediately after you click “Close Master View”. As such, be sure to PRESERVE YOUR LAYOUTS by clicking the thumbtack icon just prior to closing out of the Slide Master View.

preserve-your-layouts

There’s this really strange feature in Word called a “hanging indent” paragraph.

Hanging indents get activated when you press “CTRL+T”.
To undo a hanging indent, you can simply do any of:

a) Press CTRL+SHIFT+T
b) Click on the 2nd line and drag the indent bar back
c) Right click the second line, click Paragraph, then remove the indentation from that line.

TortoiseGit has a really great Word Document Comparison feature that you can use.

First, install PanDoc, then edit your .gitconfig to add the capability to GIT to decipher and compare Word files.

# Your .gitconfig is in C:\Users\William (where William is your Windows user name)
# Minimum required changes to your .gitconfig to enable Word doc comparisons
[diff "pandoc"]
 textconv=pandoc --to=markdown
 prompt = false

Next, install TortoiseGit.

In addition, you need to edit your .gitattributes file in your git project’s folder (add one if you don’t already have one in the root of your project).

# .gitattributes file in root folder of your git project
*.docx diff=pandoc

After you do this, if you right-click compare two .docx files, you will be able to compare them with each other. The first document clicked is the original document (top pane), the second document is the revised edition (bottom pane).

The changes to the final document (left pane) will be as if someone has gone through and edited original document with track changes on, using the changes that are in revised document.

word-diff3

Loading .gif’s in Win32 is really easy through a GDI+ pathway.

The short of it is something like this:

#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
// .. main()
Image *image = new Image( "image.gif" );

Functions are located here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms534462(v=vs.85).aspx

An example is here: https://github.com/superwills/eternity/blob/master/eternity/GDIPlusTexture.cpp#L133, or here.

You have to do File | Save As… then hit the Attributes button at the bottom

downmix

There’s a really simple dialog in File | Batch Processing… / Convert which lets you downmix a bunch of files at once also.

 

 

A bit of a weird issue, when you declare a static variable in VS 2015 you can initialize it in the member declaration:

// Unit.h
struct Unit
{
  static const char Character = 'P'; // class-level var
  char symbol; // member var
  Unit()
  {
    symbol = Character; // init with static var
  }
};

Something weird happens with the compiler sometimes however. On multiple compile/runs, the variable of the static const char Character, when changed, doesn’t bake properly into the exe.

To fix this, just split the declaration and initialization into a corresponding .cpp,

// Unit.h:
struct Unit
{
  static const char Character; // class-level var, init in .cpp
  char symbol; // member var
  Unit()
  {
    symbol = Character; // init with static var
  }
};

// Unit.cpp
const char Unit::Character = 'P';

There’s an odd thing that can happen in Windows 10 when you try to change your monitor settings with the NVIDIA Control Panel. When you try to change some multi-display settings, you may get the following dialog, stating:

“Your changes cannot be applied right now. This may be due to any of the following reasons:

  • A video is playing or a video application is running
  • A game or 3D application is running in full-screen mode
  • A command prompt window is running in full-screen mode
  • You have rotated your desktop with the Rotate Display page
  • The Display Optimization Wizard is running

You can try to apply your changes again after resolving the conflict.”

Screenshot 2016-02-06 09.03.05

I resolved this by closing Skype of all things. Even though you wouldn’t suspect a program like Skype would violate the above constraints, it does.

You can use the Add Divisions dialog for this.

Click Edit Mesh / Add Divisions.

If you add the divisions as LINEAR QUADS, you get a nice subdivisioning like so:

To Bind a hand-held weapon to a mesh (when the mesh is a single mesh as UE4 requires) keep the bones SEPARATE (unparented) when you first bind, then parent the bones together AFTER mesh bind. This prevents mesh pieces from different weapons from receiving influence from bones intended for different meshes.

binding-weapons

I found this problem coming up after I:

* Had a mesh that I wanted to adjust
* Detached skin & adjusted the mesh by moving faces
* MOVED/ROTATED A CONTROLLER which had Orient Constraints & Point Constraints on a bone for the mesh
* Tried to re-bind the bones & skin, which caused the error

The solution was: Delete the moved controller, then delete any IK handles upstream of the moved controller (maybe even all of them).

When creating an animation of a cloth for example, you may like to take a snapshot of one frame and save it into the mesh.

To do that you use Animate / Create Animation Snapshot. …

The settings that work for cloth are:

Start Time: Whatever
End Time: Whatever
Increment: any

Update: FAST (update only when keyframes change)

If you use On Demand or Slow Updates, the animation snapshot won’t work for cloth

animation snapshot

All objects in Maya are actually accessible by string.

So when you type

$var = `select -r objectName1`;

Maya will select that object in the viewport.

But $var doesn’t contain anything but a string! It just contains the string name for the current selection.

To iterate in maya, you need to use the polyEvaluate function, which retrieves things like the NUMBER of faces or vertices a polygon has.

Access of individual members of the polygon is by string:

Vertices: polyName.vtx[index]
Faces: polyName.f[index]
UV’s: polyName.map[index]

It turns out that the .vtx, .f, and .map are NOT objects. They don’t have a .size() member or anything, they’re just “string addresses”. When you address polyName.f[0], that’s the first face in the mesh. You have to pass the string address to a function to use it though.

Gotchas:

Declaring arrays with a leading 0 doesn’t work.

Move to origin:

// Zero transformation on manipulator (world space).
move -rpr 0 0 0
// Freeze transformations afterward to park manipulator @ origin
// Zero the transformation on object (local space)
string $objects[] = `ls -sl`;
$obj = $objects[0];

setAttr( $obj + ".translateX" ) 0.0;
setAttr( $obj + ".translateY" ) 0.0;
setAttr( $obj + ".translateZ" ) 0.0;

setAttr( $obj + ".rotateX" ) 0.0;
setAttr( $obj + ".rotateY" ) 0.0;
setAttr( $obj + ".rotateZ" ) 0.0;
// CLEAR KEYFRAMES
int $maxTime = `playbackOptions -q -max`;
for( $i = 0; $i <= $maxTime; $i++ )
{
  currentTime $i;
  timeSliderClearKey;
}
// left leg / right leg copy.
// use: select src controller, dst controller then
// run the script.
proc copyKeyframes( string $o1, string $o2, int $kf1, int $kf2, int $maxTime )
{
  // TRANSLATION
  copyKey -time $kf1 -attribute translate $o1;
  pasteKey -time $kf2 -attribute translate $o2;
  // if the dst frame is frame 0, also copy into end frame
  if( $kf2 == 0 ) { pasteKey -time $maxTime -attribute translate $o2; }
  
  // ROTATION
  copyKey -time $kf1 -attribute rotate $o1;
  pasteKey -time $kf2 -attribute rotate $o2;
  // if the dst frame is frame 0, also copy into end frame
  if( $kf2 == 0 ) { pasteKey -time $maxTime -attribute rotate $o2; }
}

int $maxTime = `playbackOptions -q -max`;
string $objects[] = `ls -sl`;
$o1 = $objects[0];
$o2 = $objects[1];
int $kf = 0;
while( $kf <= $maxTime )
{
  $kf = `findKeyframe -time $kf -which next $o1`;
  $kf2 = ($kf + $maxTime/2) % $maxTime;
  print $kf;
  print " ";
  print $kf2;
  print "\n";
  copyKeyframes( $o1, $o2, $kf, $kf2, $maxTime );
  $kf++;
}

You can actually apply multiple textures to the same object group in maya. Simply select a set of faces and right-click-drag the desired material to the faceset.

The Move Tool: axis reflection of manipulation

The move tool has the ability to reflect selection and manipulations of vertices across an axis plane.

Go to Window / Settings/Preferences / Tools Settings to change the properties of the move manipulator tool.

The dialog box looks as follows:

Scroll down inside the Tool Settings dialog until you come to Reflection Settings and hit the checkbox beside Reflection:

Select the Reflection Axis as either X, Y or Z, and experiment with it.

Get a Rotator facing a certain direction:

use FVector::Rotation()

There’s a really great article about emotion combinations here.

A very interesting diagram!

MaslowsHierarchyOfNeeds-1

UE_LOG is easy to use! There are just a couple of tricks that you need to know.

  1. Always use the TEXT() macro
  2. When LOGGING an FSTRING, always preceed the FSTRING with *

Examples:

Plain text

UE_LOG( LogTemp, Warning, TEXT("A log message") );

Printing an FString

To print an FString into a UE_LOG() message, you have to remember to preceed the FString

UE_LOG( LogTemp, Warning, TEXT("%s"), *actor->GetName() );

To print an FString into a UE_LOG() message, you have to remember to preceed the FString

UE_LOG( LogTemp, Warning, TEXT("%s"), *FString::Printf( TEXT( "%f" ), 47.f ) );

Goals.

Any goal that you set has a timeframe. The further out your “goal” is (basically how long it will take you to get there) determines how “realistically” you can actually achieve that goal. If a goal should not be achieved, then it should be abandoned and another goal set instead.

Say for example I have a goal of having a cup of coffee this morning. That’s an almost 100% achievable goal. But say I want to become the mayor of my home city. That goal is pretty much more difficult to achieve, since the number of intermediate steps (time) to get to that result is large.

How to achieve a goal (no matter how large)

Let’s take the example of becoming the mayor of a city called Pickering. That goal is pursued in a series of small steps. The steps might be like

  1. graduating from school for political science (unfortunately there are no schools for “mayoring”)
  2. doing volunteer work here and there to better know the city you want to be the mayor of
  3. doing an internship in a city office

ITERATE ON YOUR GOALS IN SMALL STEPS. Take into consideration CURRENT STATE of the system at each step to determine if you should CANCEL the GOAL or continue pursuing it. The higher the cost of the step, the more costly cancelling is, which is why you iterate in small steps.

I’ll use the Warcraft 3 video game as an example. If you haven’t played it, go and try it! It’s a great game.

The main goal of Warcraft 3 is to dominate the map by destroying all your opponents. You want a maximum number of resources also. So, say for example, you plan an early expansion in order to win the game. That may or may not be a good goal, depending on what your opponent is doing.

Say for example, you scout early and notice they are planning a rush. Your goal of expanding out to the nearby goldmine must be cancelled, or you’ll lose.

DON’T CHOOSE SOME ARBITRARILY DIFFICULT FINAL GOAL STATE FOR YOURSELF (for example, I want to marry “Josephine” (whoever that is)) and run for it despite “Josphine” not even possibly being an ideal mate for you. Your initial goal may be wrong for you. You make selections of what your goals are based on your current state. If your current state changes (for example, you lose a leg), then the goals you set for yourself may be wrong for you at that changed state.

Say Josephine is an athlete, and you are one also. Is Josephine still a good choice for you (will both you and her be happy together with you in the “leg lost” state?) Could be, if she doesn’t mind her husband having 1 leg!

You always have to re-evaluate your long-term goals as you are pursuing them. If they are the wrong goals for you, then change them!

Often, people who run academia are concerned that their methods of evaluation of human intelligence might not be as accurate as they need to be.

If a student is lazy, and doesn’t do any work, and so achieves low marks, is it fair to say that student is not very intelligent? Probably not, but it’s what people do.

So, there must be some biological basis for intelligence that could be used to rate the intelligence of a person.

Try browsing this paper on dendrite structure. In my thinking, I hypothesize intelligence could be measured by 3 things:

1 – speed at which they learn [physically: formation of neural connections]
2 – amount of information they can retain after learning [how intact the biology stays]
3 – speed of recall information previously learned (“replay”) [space between dendrites, quality of white or gray matter between dendrites]

But here’s the thing. Learning snowballs. If you understand how to do addition already, learning to do subtraction will be learned much faster than if you didn’t already understand addition to begin with.

Learning is only possible, however, if you are paying attention and understand what is being said. Biologically, this should be measured by the speed of formation of new synapses or connections in the brain.

A good class is “fun” and easy to learn/remember because it puts the brain in an entertained state which makes learning easier because the brain is more active in that state, so more neural connections can physically be formed.

Even a good movie is easy to remember (usually) because it puts the brain in an excited state, which makes information storage in the brain more likely to stick.

how to be happy.

1. have something to compete in that you find challenging, but can win at (sometimes). (winning all the time can be boring!). too much of this makes you a “jock”, which isn’t a bad thing.

2. something to grow and look after. students, children, a garden, etc. too much of this without being paid well for it will make your life appear unappreciated.

3. sex, food, bodily pleasures. too little of this can make you feel deprived, need just the right amount.

I created tradevertise recently. The idea is to find stuff that is close to you and trade with local people.

The internet changed things. It changed how information is shared. We went from knowledge being parked away in books at the library, to information being available at your finger tips, on your phone, while you’re in the bathroom. People have more free access to information than ever before. And it’s use to ARPANET!

Is that good? For consumers, yes! For producers? Maybe not.

I wonder what computer jobs were like in the 80’s. When the know-how of how to create a database schema was parked away inside a lengthy tome that only the senior engineer could grok. Now, that information, the answer to that same question you’ve had and would have spent days searching for the answer to, is now available in an online catalog. Got a problem? Go to google, type in your query.

Google changed things. Google indexed the internet. Google is like the computer catalog in the library.. except Google is slowly becoming the front end to all human knowledge that anyone cared to enter into the internet.

So information is transferring.. from humans, to machines. stackoverflow.com represents a corpus of knowledge that far superceeds what a single programmer could ever learn in his lifetime. It is the accumulated knowledge of what many programmers have learned in their lifetimes. And it doesn’t forget. Except for mod-delete.

So people just drop all they know into the internet. They get a +1! Thanks! But not paid for their contributions, which could potentially reach 100’s of people, some of which are corporations, businesses, places that will make money on what you’ve given away for free.

Now who gets paid? Let’s see.

  • Google: Advertising
  • Sites that host content: whatever they manage to make on ads or the sale of other services
  • Actual Internet Contributers: 0

So, what’s the deal? Smart people are not that important if their knowledge, ability to learn, ability to retain knowledge is not important (since machines cover that..)

But what if smart people all of a sudden stopped existing? Say suddenly, all your savants just stopped being savants, and all you had were non-nerdy people. Then the machines would stop learning :). The indexes would have less to index. And maybe humanity wouldn’t progress as quickly.

Your Academic Career Is Just Masturbation

What is state of the art in industry? Take a look at that.

Now take a look at your MSc or PhD paper. Back to state of the art in industry. Back to your MSc or PhD paper. Your MSc is now irrelevant.

The fact of the matter is, most of the work done in Universities for MSc or PhD work isn’t very good. In fact, it’s below not very good. It’s downright abysmal.

Nobody needs you to write about the role of a specific gene, or yet another computer vision thesis. US government labs, and industry labs already have research superceeding what you spent the last 3 years working on by decades.

It’s only logical. Research builds on what came before it. The state of the art, in computer vision, for example, is top secret — if those algorithms were released, it would be a security hazard for the US. The US military doesn’t publish its cutting edge research for a reason! It took the US military decades of research to get its flight control software to where it is today. I don’t mean to discourage you, but the tendency for smart people is to let their brains get to their head. You have to realize what you’re up against when you try to prove you know something to the world: the world collectively knows a lot more than you do.

So chill out. Calm down. Check yo’ self. What you’re doing in academic work is not that important. Technologies come and go in industry like you wouldn’t believe. The bottom line is, if it doesn’t make money, nobody cares about it.

Your research is only a means to an end. The end is get the jobs you want. The means justifies your being able to get those jobs to everyone around you.

Say you’re inventing yet another programming language to make writing code “faster and more efficient”. That doesn’t matter if your faster and more efficient code doesn’t get sold or seen by anyone. Are you an avid participant in stackoverflow.com, with 100k reputation? Stop that. You are masturbating. And according to lore masturbating could give you hairy palms or even sudden death. Do you get happy when you see imaginary points rack up in social karma sites? Big mistake. You’re conditioned by the gamification of social websites into thinking that the “work” you’re doing by helping others is actually useful. It’s not. By spending time on programming forums not making money and “pursuing knowledge”, you’re effectively wasting your life.

So what do you need?

You need sales. You need customers. You need relationships.

Take a look at the Google Graveyard. Leave your flower. If you’re a code geek, the effect should be chilling. Don’t make me spell it out for you. The vast majority of coding projects die. The vast majority of startups die. The .COM bubble burst because there was no money coming out of these websites that looked promising but offered services for free.

Balance your life

If you are doing an academic degree and are still single, you’re in huge trouble. Because the social aspect of your life is yet undeveloped, and you think your research is so important. Go out and have a beer. Have 2 beers. Mix and mingle. Have sex. Have plenty of sex. Get a partner. Sex is very important because it will develop you socially.

The social aspect in a company isn’t just “50% of the work we do”. The social aspect is everything. If you’re not social, you won’t have a good career.

It was great when it first came out. A competitor to DirectSound that worked on all systems. It still is kind of good.

But, the problem is, it _started out_ free, open, with no licensing fees, and cross platform. People promoted it widely, everyone paid attention, and many adopted it, after all it was “Free! No licensing fee!”

Then Creative Labs took over OpenAL and made it proprietary. But people continued to use OpenAL 1.1… since OpenAL 1.1 “works well enough” it isn’t being updated or maintained, and it continues to see widespread use.

However other sound systems such as FMOD or DirectSound have made many improvements over the base functionality OpenAL 1.1 provides.

The result of OpenAL 1.1 being available is a whole ton of systems is it became very old very fast, it still works, but not nearly as competitively as it did in 2008, for example. And there’s little chance of the situation for OpenAL The Free And Zero Licensing Cost Audio Software of being maintained by the open source community.

I keep coming across code like

for( int deviceIndex=0; deviceIndex < devices.size(); deviceIndex++ )
{
    devices[deviceIndex].something();
    devices[deviceIndex].param += value;
}

what’s wrong with this code? wouldn’t it be a lot better like this?

for( int i=0; i < devices.size(); i++ )
{
    devices[i].something();
    devices[i].param += value;
}

i is a dummy variable. It’s name doesn’t matter – it just needs to be short. devices[deviceIndex] is redundant – we already know what we are accessing by the array’s name, devices[deviceIndex] is just longer and noisier than devices[i] – without adding additional clarity.

Just came across this in a C code apple example:

do
{
  // stuff..
} while (false);

The code breaks the loop when an error occurs inside it. This is kind of like try/catch/finally, where you have a simple catch(…) all block that you jump to if you “break” the loop. It seems like a poor substitute for a function call however.

Some artifacts may arise. For example, say you inherit from std::string. You want to write a function that ends up calling a method from std::string that returns a std::string: (like .substr()). Now you have an extra ctor call to construct your derived type object —

I’m testing polldaddy polls. Here’s the link.

The weirdest shit. You have to ask OpenGL to normalize byte colors. So the correct call to glVertexAttribPointer would be:

glVertexAttribPointer( attribNo, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, squareColors);

I spent like 20 minutes looking for what the problem could be with my code when I tried to switch float colors to byte colors, all my colors were white. And it was just this `normalized` flag.

I effectively had this:

void fun( const char* msg )
{
  function = [msg](){
    // do something with msg
  }
}

Then call:

fun( string( "oh hi hello" ).c_str() ) ;

See what’s wrong? The string object whose char* ptr I passed to fun _dies_ immediately after the line executing call to fun runs. So the captured const char* ptr [msg] is invalid if function() runs at a later time (after return of call to fun())

nov 20 2013 4:22p

The item that an enemy would go for was flip flopping. It would continually flip between chasing after the 2 nearest items. I detected this bug in 2 minutes on the 1st launch, because I had inserted printf statements.

– Detection: printf statements
Enemy squadron Fighter thinks item B1 is reachable in 2.703664 seconds
Enemy squadron Fighter thinks item Bandit is reachable in 2.884945 seconds
Enemy squadron Fighter thinks item B1 is reachable in 2.703305 seconds
Enemy squadron Fighter thinks item Bandit is reachable in 2.884617 seconds

Reason: units were programmed not to chase after items that units on their same team were chasing after. Unfortunately overlooked the fact that I would be seen on as on my same team.

Solutions:
– If I’m already gathering an itembox, stick with it until i get it OR
– If the person gathering the itembox is ME, keep going after it.


Using integer indices into arrays of objects (instead of iterators, or pointers to the objects themselves) has saved my ass many times.

Say you have a vector<Object>. Well, you wouldn’t store pointers of type Object* to an element of this array, ever, because if the vector gets resized, all objects get deallocated/reallocated and so all your previous references will be invalid. But if you store a vector<Object*> and save an external reference to an Object* within that vector, then that’s no problem.

But anyway, storing integer arrays is much better than storing copies of pointers. For one, if the pointer gets deleted, you’re not left with an invalid / dangling pointer somewhere. Checking if a reference into the array is valid because you just have to check the integer index is between 0 and (.size()-1).

Simple example


f := (x) -> x^2

Is the function f(x)=x^2. You call it by writing


f(2)

To animate the function, just add another parameter and give it a range in a plot command.


plot( a*f(x), x=-2..2, a=0.1..5 )

C++’s RTTI is expensive. Very expensive. Notoriously and verifiably expensive.

So how can we efficiently get information of the concrete subclass, given an abstract base class pointer, without the great expense of using RTTI?

Simple. Use an enum.

Consider the example in my stackoverflow post. What I did there is just keep a single bitfield (an int) that has concrete types bitwise OR’d in, in each derived constructor.

So, in the example posted, an object of Type BigCat would have 0111 for its typeTag field, indicating that it is an Animal, a Cat, and a BigCat. Concrete type checking is cheap as a bitwise AND.

eta is easy to compute if you have distance between 2 objects, their relative accelerations, and relative velocities.

By _relative_ accelerations and velocities, i mean the rate at which they are coming together. So you have to project both objects’ velocity components onto the line joining the two objects, and use that scalar component in these computations.

Without further ado, eta:

eta = -v1 +/- sqrt( v12 + 2a(dist) ) / a

In image:

I ran into this error before, it is described here. Basically preface whatever the offending line is with this->.

Did you know if you work in “High Quality Rendering” mode (click the red box) the split polygon tool is _much more helpful_?

What’s wrong with this code?

class Object{
  int x ;
  Object() {
    defaults() ;
  }
  Object( int ix ) : x(ix) {
    defaults() ;
  }
  
  defaults() { 
    x=0;
  }
} ;

Well, obviously x has the value 0, instead of the initializer-list desired default value sent `ix`.

So, what happens when you have 10-15 members that all have default value initialization in defaults(), and possible assignment in the initializer list, is defaults() clobbers whatever was sent to the initializer list, since the initializer list runs first.

I puzzled over this for a few minutes.

Warcraft 1,2 & 3 used swords for attack, shields for stop. It works because the entire theme was medieval. So, swords mean attack, shields mean “stop”. Regardless of unit type (even air units — there’s no cognitive dissonance there).

Starcraft 1 & 2 cleverly abstracted this away though. Swords clearly wouldn’t fit in Starcraft. Different units had different means of attacking. Zerg never use guns. They use spit or claws. Protoss had some “sword-like” units that did hand-to-hand combat (zealots), but other units fired projectiles (dragoons). They used a _crosshair_ instead for the attack symbol.

So, in my own game I had to think, what symbolizes _attack_ in my game? It’s a space combat game, and attack is done primarily via missiles. So I subbed in a picture of a missile for attack. And voila. The right symbol for attack is _a picture of whatever attacking is done with_ in your game.

If it were a streetfighting game, you’d use an icon of a fist.

I couldn’t find a way to do this through the GUI, but I’m positive there was one.

Anyway, the MEL command to show normals for the selected mesh:

polyOptions -dn 1;

And to hide them again

polyOptions -dn 0;

Taken from here

Maya rotate snap hotkey is j

j means rotate snap, because you know, in original english rotation by discrete amounts of 15 degrees was called “jotation”.

Anyway, double clicking the ROTATE TOOL gives you a box @ right, you can modify the size of the discrete step there.

If you notice, holding j “temporarily” clicks on the “discrete rotate” setting.

Maya vertex snap hotkey is v

If you hold v it will let you snap a vertex to another one while dragging.

Maya show vertex location

Maya is a visual editor, so they actually hid the information of the numerical coordinates of the vertices pretty well.

You can usually get the results you want by snapping. But when you can’t, there’s the Component Editor.

You go to Window / General Editors / Component Editor to get it. I learned this from a SimplyMaya thread.

I almost forgot the simple formula for checkerboarding,

if( (i % 2) == (j % 2) )  WHITE;
else BLACK ;

If both i and j are EVEN, OR both i and j are ODD, you get one color. If they differ in “oddness” then you get the other color.

There is a really shitty post on stackoverflow about this, filled with nonsense.

I’m working with old OpenGL code. Specifically, code based off GLES2Sample.

There was a slight change around iOS 5.0 or so, requiring you to have a root view controller. If your code is based off older sample code, such as GLES2Sample, then no root view controller was created in those code samples.

To fix GLES2Sample, I know the following fix works. Right in `applicationDidFinishLaunching`, I create a root view controller and attach my glView to it.

    - (void) applicationDidFinishLaunching:(UIApplication *)application
    {
      // To make the 'Application windows are expected
      // to have a root view controller
      // at the end of application launch' warning go away,
      // you should have a rootviewcontroller,
      // but this app doesn't have one at all.
      window.rootViewController = [[UIViewController alloc] init];  // MAKE ONE
      window.rootViewController.view = glView; // MUST SET THIS UP OTHERWISE
      // THE ROOTVIEWCONTROLLER SEEMS TO INTERCEPT TOUCH EVENTS
    }

That makes the warning go away, and doesn’t really affect your app otherwise.

Developer journals are my answer to dead code. Word Documents, blog entries, whatever. Source control history is harder to wade through than dated log entries about how a function used to work, and how it works now.

Logging with thoughts on what changed and why it changed is essential, even if you’ll never refer to it, the peace of mind you get while simultaneously retaining a clean code base is worth it. Delete with confidence – and a backup. Plus, you’ll never get the clarity why you deleted something as when the moment you deleted it.

Here’s an example of a journal entry I just made for today:

This is part of a Word document. I just downsized the font so it is quickly scrollable. I doubt I will need the comments or dead code I am about to delete, or that I will be unable to regenerate them easily, but just in case, the info is all there in this dated entry.

This article confirmed my suspicion.

Besides a wide variety of flavors and roast selections (with French Vanilla available as a light roast), Target’s coffee is indeed my cup of.. coffee.

So far I’ve only began the French Vanilla bag, but it tastes delicious. It actually tastes a lot like coffee shop coffee. It’s very fresh, very smooth, and the vanilla flavoring is just right — not overpowering, but pleasantly tasty.

I also got the plain light roast. It costs about $3.50 less than a bag of Starbuck’s blonde, if it’s good, it will probably be my new main.

There’s this point in Woo’s paper that confused me before, and it just confused me again now.

The paper says to always pick the largest t.

So the situations in red and pink confused me. It would seem at first glance that “further t” (in the pink diagram, the one intersecting min.y) would be the “greater t” but the _wrong one_ to pick.

But it turns out when you cull the back faces _based on ray direction_, the smaller t would be at the max.y plane, even though the ray starts AFTER the max.y plane.

Note Woo’s method as presented _doesn’t work for when the ray starts totally inside the box_.

If the ray starts inside the box, if you only need the boolean result then RETURN TRUE immediately. But if you need the intersection point, you need to turn around some of the rules of the test:

From “Geometric Tools for Computer Graphics”, the definition of convex given on pg 265 sec 7.7 is:

A set S is convex if given any two points P and Q in S,the line segment ( 1 − t ) P + t Q for t ∈ [0, 1] is also in S.

Said more plainly, if every line you can draw that connects two vertices a shape is completely contained inside the shape (tracing edges is allowed), then that shape is convex.

Basic program showing how to use GLSL and GLUT together

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <map>
using namespace std ;

#define _USE_MATH_DEFINES
#include <math.h>

// REMEMBER TO INSTALL GLEW! http://glew.sourceforge.net/install.html
// 
// 2 WAYS TO COMPILE GLEW:
// 1)  AS A STATIC LIB.
//     #defining GLEW_STATIC means to compile the glew library as a static lib.
//     This means your prog WILL NOT require the glew32.dll file to accompany your executable.
//
// THIS IS HOW YOU COMPILE GLEW AS A STATIC LIB:
#define GLEW_STATIC
#include <GL/glew.h>
#pragma comment( lib, "glew32s.lib" )   // the 's' is for 'static'

// 2)  AS A DYNAMIC LIB:
//     THIS REQUIRES YOU INCLUDE glew32.dll WITH YOUR FINAL EXECUTABLE/HAVE IT INSTALLED.
//#include <GL/glew.h>
//#pragma comment( lib, "glew32.lib" )

// I'm using the STATIC LIB way above, because I prefer it.

#include <GL/glut.h>

GLuint glslProgId ;     // GLSL shader PROGRAM identifier
GLuint vshId, pshId ;   // GLSL vertex shader id, pixel shader id

// These 2 are "handles" that connect the POSITION attribute in
// the GLSL shader with __AN ACTUAL SET OF VERTICES__ from the C++ source code.
// In this program each VERTEX has a position and a color (only).
GLuint positionAttribute, colorAttribute;

// This is the connector between the uniform variable modelViewMatrix,
// used in the glsl shader code.  We need this variable to LOAD
// a specific modelview matrix INTO the GLSL shader before rendering the verts.
GLuint uniformModelViewMatrix;

// The vertex array object identifier.  This single number
// identifies EVERYTHING about the vertex buffer we are 
// about to create and render, from its attribute set (positions, colors)
// to where to fetch the data from when it's time to draw.
GLuint vao ;

// window width and height.
float w=512.f, h=512.f;

struct VertexPC
{
  float x,y,z, r,g,b,a ;
  VertexPC( float ix, float iy, float iz, float ir, float ig, float ib, float ia ):
    x(ix),y(iy),z(iz), r(ir),g(ig),b(ib),a(ia)
  {}
} ;

// The data for the vertex and index buffers.
// I'm just using index buffers to show how they are used.
static VertexPC verts[] = { 
  VertexPC(0,0,0, 1,0,0,1),
  VertexPC(1,0,0, 0,1,0,1),
  VertexPC(0,1,0, 0,0,1,1)
} ;
static int indices[] = {0,1,2};

map<int,const char*> glErrName ;
// GL ERR
map<int,const char*> createErrMap()
{
  map<int,const char*> errmap ;
  errmap.insert( make_pair( 0x0000, "GL_NO_ERROR" ) ) ;
  errmap.insert( make_pair( 0x0500, "GL_INVALID_ENUM" ) ) ;
  errmap.insert( make_pair( 0x0501, "GL_INVALID_VALUE" ) ) ;
  errmap.insert( make_pair( 0x0502, "GL_INVALID_OPERATION" ) ) ;
  errmap.insert( make_pair( 0x0503, "GL_STACKOVERFLOW" ) ) ;
  errmap.insert( make_pair( 0x0504, "GL_STACK_UNDERFLOW" ) ) ;
  errmap.insert( make_pair( 0x0505, "GL_OUTOFMEMORY" ) ) ;
  
  errmap.insert( make_pair( 0x8CD5, "GL_FRAMEBUFFER_COMPLETE" ) ) ;
  errmap.insert( make_pair( 0x8CD6, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT" ) ) ;
  errmap.insert( make_pair( 0x8CD7, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" ) ) ;
  errmap.insert( make_pair( 0x8CD9, "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS" ) ) ;
  errmap.insert( make_pair( 0x8CDD, "GL_FRAMEBUFFER_UNSUPPORTED" ) ) ;                    
  return errmap ;
} 

inline bool GL_OK()
{
  GLenum err = glGetError() ;
  if( err != GL_NO_ERROR )
    printf( "GLERROR %d %s\n", err, glErrName[ err ] ) ;
  return err == GL_NO_ERROR ;
}

inline bool GL_OK( int line, const char* file )
{
  GLenum err = glGetError() ;
  if( err != GL_NO_ERROR )
    printf( "GLERROR %d %s, line=%d of file=%s\n", err, glErrName[ err ], line, file ) ;
  return err == GL_NO_ERROR ;
}

inline bool CHECK( bool cond, const char* errMsg )
{
  if( !cond )  puts( errMsg ) ;
  return cond ;
}

// WITH LINE NUMBERS
#define CHECK_GL GL_OK( __LINE__, __FILE__ ) 

// WITHOUT LINE #s
//#define CHECK_GL GL_OK()

void printShaderInfoLog(GLuint obj)
{
  int infologLength = 0;
  
  glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &infologLength ) ;
  if( infologLength )
  {
    char *infoLog = (char *)malloc(infologLength);
    int charsWritten ;
    glGetShaderInfoLog( obj, infologLength, &charsWritten, infoLog ) ;
    puts( infoLog ) ;
    free( infoLog ) ;
  }
}

void printProgramInfoLog( GLuint obj )
{
  int infologLength = 0;
  
  glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &infologLength ) ;
  if( infologLength )
  {
    char *infoLog = (char *)malloc( infologLength ) ;
    int charsWritten ;
    glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
    puts( infoLog ) ;
    free( infoLog ) ;
  }
}

void setupShaders()
{
  // The text of the shaders.  I put it as an inline string
  // just so I could post this easily w/o external files,
  // but you could easily load the shader from an external file.
  // The point is, you must pass your shader to OpenGL as
  // just a NULL terminated string.
  const char *vs = 
    "uniform mat4 modelViewMatrix ;                         "
    "                                                       "
    "attribute vec3 position;                               "
    "attribute vec4 color;                                  "
    "                                                       "
    "varying vec4 Color;                                    "
    "                                                       "
    "void main()                                            "
    "{                                                      "
    "  Color = color;                                       "
    "  gl_Position = modelViewMatrix * vec4(position,1.0) ; "
    "}                                                      " ;

  const char *fs =
    "in vec4 Color;            "
    "                          "
    "void main()               "
    "{                         "
    "  gl_FragColor = Color ;  "
    "}                         " ;
  
  vshId = glCreateShader(GL_VERTEX_SHADER) ;  CHECK_GL ;
  glShaderSource( vshId, 1, &vs, NULL ) ;  CHECK_GL ;
  glCompileShader( vshId ) ;  CHECK_GL ;
  printShaderInfoLog( vshId );
  
  pshId = glCreateShader(GL_FRAGMENT_SHADER) ;  CHECK_GL ;
  glShaderSource( pshId, 1, &fs, NULL ) ;  CHECK_GL ;
  glCompileShader( pshId ) ;  CHECK_GL ;
  printShaderInfoLog( pshId );

  glslProgId = glCreateProgram();
  glAttachShader( glslProgId, vshId );
  glAttachShader( glslProgId, pshId );

  glLinkProgram( glslProgId );
  printProgramInfoLog( glslProgId );

  positionAttribute = glGetAttribLocation( glslProgId, "position" ) ;
  colorAttribute = glGetAttribLocation( glslProgId, "color" ) ; 

  uniformModelViewMatrix = glGetUniformLocation( glslProgId, "modelViewMatrix" ) ;

  
  
  // Make a "vertex buffer"
  GLuint vertexBuffer ;
  glGenBuffers( 1, &vertexBuffer ) ;

  // LOAD THE DATA INTO IT:
  glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer ) ;
  glBufferData( GL_ARRAY_BUFFER, sizeof( verts ), verts, GL_STATIC_DRAW ) ;

  // Make an "index buffer"
  GLuint indexBuffer ;
  glGenBuffers( 1, &indexBuffer ) ;
  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer ) ;
  glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW ) ;



  //// SET UP THE VAO
  // You know, this is weird, but a VERTEX ARRAY OBJECT
  // DOESN'T ACTUALLY STORE DATA.
  // Vertex BUFFERS store the data.
  // A VAO stores the SETUP of how a group of
  // vertices is to be rendered.
  // That is, it stores:
  // 1)  The DATA (in vertex BUFFERS) to be drawn
  // 2)  THE SEMANTICS of that data (vertex format)
  // 3)  THE LINKAGE TO THE SHADER THAT WILL BE USED TO DRAW THIS DATA.

  // So you can see, it's all very intermingled and messy.
  // TO draw vertex data with GLSL, you have to:
  //   1) Load the raw vertex data into a vertex buffer
  //   2) set up vertex attributes (via glVertexAttribPointer)
  //      WHICH does 2 things:
  //      a)  It tells OpenGL the VERTEX FORMAT (floats? 3 elements? 4 elements? stride?)
  //      b)  It tells OpenGL THE SHADER VARIABLE THAT THIS VERTEX ATTRIBUTE LINKS INTO.
  //   3) Call glDrawArrays or glDrawElements( ..., 0 ) 
  //      
  // INIT THE VERTEX ARRAY (stuff to draw)
  // The vertex array OBJECT remembers info about
  // WHAT VERTEX ATTRIBS ARE TO BE BOUND, to what
  // indices, and the actual vertex buffer object
  // from which to pull data when rendering.
  glGenVertexArrays( 1, &vao ) ;
  glBindVertexArray( vao ) ;

  glBindBuffer( GL_ARRAY_BUFFER, vertexBuffer ) ;
  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer ) ;
  
  glEnableVertexAttribArray( positionAttribute ) ;
  glVertexAttribPointer(
    positionAttribute,  // index. NOTE THIS HAS BEEN CONNECTED UP EARLIER
    // WITH THE VERTEX SHADER THAT WILL BE USED TO RENDER THIS VERTEX ARRAY
    // IN THE LINE:
    //   > positionAttribute = glGetAttribLocation( glslProgId, "position" ) ; // C++ code line
    // and "position" is used in the GLSL vertex shader as:
    //   > attribute vec3 position; // GLSL shader line
    // SO. Don't be confused, the `positionAttribute` variable is simply connected up
    // to the vertex shader's INCOMING "position" attribute.  Naked girls.
    3,          // size. 3 floats/vertex
    GL_FLOAT,   // type. floats!
    0,          // normalized? No.
    sizeof(VertexPC),          // stride
    0           // pointer.  0 says to use the CURRENTLY BOUND
    // VERTEX BUFFER (WHATEVER THAT IS AT THE TIME OF THE DRAW CALL).
    // If you want to draw from CLIENT MEMORY you would pass AN ACTUAL ADDRESS
    // here (BUT YOU MUST MAKE SURE TO HAVE NO VERTEX BUFFER BOUND BECAUSE THEN
    // THE MEMORY ADDRESS YOU PASS HERE WOULD BE INTERPRETTED AS AN __OFFSET__
    // INTO THAT VERTEX BUFFER, TRIGGERING A SEGFAULT/OUT OF BOUNDS EXCEPTION TYPE THING.)
  ) ;

  glEnableVertexAttribArray( colorAttribute ) ;

  int offset = 3*sizeof(float) ;
  glVertexAttribPointer( colorAttribute, 4, GL_FLOAT, 0, sizeof( VertexPC ),
  
    (void*)offset  // RE: THE LAST PARAMETER: I know it looks ridiculous!! to pass a NUMBER as cast to VOID* here,
    // but that's C api's for you.  "Wait! Shouldn't it be &offset?"
    // NO. Your eyes kid you not.  You take the INTEGER NUMBER (which amounts to 12 here)
    // AND JUST PASS THAT AS IF IT WERE A "VOID*" POINTER. Even though you and I know it is not.
  ) ;

}

void keyboard(unsigned char key, int x, int y)
{
  switch(key)
  {
    case 27: //esc
      glDeleteVertexArrays( 1,&vao ) ;
      glDeleteProgram( glslProgId );
      glDeleteShader( vshId );
      glDeleteShader( pshId );
      exit(0);
      break ;
  }
}

void resizeWindow(int width, int height)
{
  w=width,h=height;
}

void draw()
{
  glViewport( 0, 0, w, h ) ;
  
  glClearColor( 0.1f, 0.1f, 0.1f, 0.1f ) ;
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;

  // Bind the shader I created earlier
  glUseProgram( glslProgId );
  
  // Update the uniform variable.  YOU CAN
  // ONLY UPDATE THE UNIFORMS OF __BOUND SHADERS__ --
  // IE glUniformMatrix4fv must be called AFTER glUseProgram
  float m[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 } ;
  glUniformMatrix4fv(uniformModelViewMatrix, 1, false, m);

  // Here we bind the vertex array "object".  This is EQUIVALENT
  // to "replaying" 
  glBindVertexArray( vao );

  // Now we could draw in one of 2 ways:

  // DRAW USING THE VERTEX BUFFER (ONLY):
  //glDrawArrays( GL_TRIANGLES, 0, 3 ) ; // draw as vertex buffer (with no index buffer)

  // DRAW USING INDEX BUFFER + VERTEX BUFFER
  glDrawElements( 
    GL_TRIANGLES,
    3, //# INDICES in the index buffer
    GL_UNSIGNED_INT, // I used 4-byte ints. Some other people use shorts, but I never do.
    0  // 0 means, use the index buffer bound
  ) ;

  glutSwapBuffers();
}

int main(int argc, char **argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
  glutInitWindowPosition(100,100);
  glutInitWindowSize( w,h ) ;
  glutCreateWindow("GLSL with GLUT");

  glutDisplayFunc(draw);
  glutIdleFunc(draw);
  glutReshapeFunc(resizeWindow);
  glutKeyboardFunc(keyboard);

  glewInit();
  //if( glewIsSupported("GL_VERSION_3_0") )

  glEnable(GL_DEPTH_TEST);
  glClearColor(1.0,1.0,1.0,1.0);

  setupShaders() ;

  glutMainLoop() ;

  return 0 ; 
}

If you’re using numerical indexing to access the xyz components of a vector, (with 0=x, 1=y, 2=z) a good tip is to remember that

axis = 0 ; // for example.
otherAxis1 = ( axis + 1 ) % 3 ; // =1
otherAxis2 = ( axis + 2 ) % 3 ; // =2

This works for all values of axis to get you “the other 2” axes