Domino’s New Gourmet Range
On the Domino's website for Brighton today had three new pizzas. And to mark the occasion they have a new gourmet deal if you buy two, you get them for £19.99 as well as some extras.
If you do not want two, then you can always just buy one from the special's option, however they cost more than a standard large, because let us not forget that they are gourmet.
Or are they? On the "Create Your Own" option they have added a lot of these new ingredients, most of which I reckon are probably just the old ones with a few new additions.
So I tried creating the first one in the list, the salami and pepperoni, and it came to £1.60 cheaper.
Ventricina Salami, Pepperoni and Peruvian Roquito Peppers on a thin crust base.
Special's Cost: £17.49
Create Your Own Cost: £15.89
Price Increase: £1.60
Baby Spinach, SunBlush Baby Plum Tomatoes and Greek Feta Cheese on a thin crust base.
Special's Cost: £17.49
Create Your Own Cost: £15.89
Price Increase: £1.60
Chicken breast strips, naturally smoked bacon rashers, baby spinach and SunBlush baby plum tomatoes on a thin crust base.
Special's Cost: £17.49
Create Your Own Cost: £17.19
Price Increase: £0.39
Accident? I do wonder if when they realise this or get told they'll reduce the cost of the pizza, increase the price of the new toppings, or just claim there is "special sauce" that costs more.
Using Vertex Array Objects
With my recent post about what iOS devices supported what extensions, I noticed a lot of people got to my website trying to work out how to use Vertex Array Objects (VAO) with the GL_OES_vertex_array_object extension.
They're easy to use so I thought I would write up a quick how-to use them. There is a limitation with the VAO however, it cannot be shared between contexts and can be problematic for multithreading.
If you plan to use one, either generate and create for each context you will be using it on. Or generate and create on the context you will be mostly using it on. It might be a mistake, since it says they didn't want to create the first non-shared named object in OpenGL ES, however at the same time they say no to sharing.
Like with any OpenGL object, first a name must be generated for the object, make sure you always initialise your name variables to 0, since this refers to a non-object.
GLuint gVAO = 0;
//
//
int main()
{
//
GenerateVAO();
CreateVAO();
//
do
{
BindVAO();
DrawSomething();
UnbindVAO();
}
while( 1 );
//
DestroyVAO();
}
//
//
void GenerateVAO()
{
// Generate Name for VAO
glGenVertexArraysOES( 1, &gVAO );
}
//
//
void DestroyVAO()
{
if( gVAO )
{
glDeleteVertexArraysOES( 1, &gVAO );
gVAO = 0;
}
}I've also put the syntax in there for deleting the VAO when you do not need it anymore.
Now for filling in the VAO. The VAO is basically a block of memory for storing vertex data schematic. For fixed function, the schematic includes information about data type, count, stride, buffer offset and whether it is enabled. This is for every pointer, glVertexPointer, glNormalPointer, glColorPointer, glTexCoordPointer, etc.
And for the shader program pipeline, it contains the schematic for each glVertexAttribPointer.
//
//
void CreateVAO()
{
// Bind VAO
glBindVertexArrayOES( gVAO );
// Bind Vertex Buffer
glBindBuffer( GL_ARRAY_BUFFER, gSomeVBO );
// Fill in the VAO with our vertex schematic
if( hasShaders )
{
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, // Attribute bind location
3, // Data type count
GL_FLOAT, // Data type
GL_FALSE, // Normalise this data types?
sizeof(float) * 3, // Stride to the next vertex
0 ); // Vertex Buffer starting offset
}
else
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, // Data type count
GL_FLOAT, // Data type
sizeof(float) * 3, // Stride to the next vertex
0 ); // Vertex Buffer starting offset
}
// Unbind VAO
glBindVertexArrayOES( 0 );
}
You'll notice that when I am finished with with the VAO, I unbind it. This is because any changes to the vertex pointers will override any we have set within this function, so to protect the VAO we have just filled in, we unbind it.
When using a VAO, you will not need to bind the GL_ARRAY_BUFFER again the next time you use the VAO, since whenever you make a call to gl*Pointer() or glVertexAttribPointer(), the vertex buffer is stored with the vertex schematic. Because of this, you can have multiple streams of data from different vertex buffers.
//
//
void CreateVAO()
{
// Bind VAO
glBindVertexArrayOES( gVAO );
// Vertex Buffer 1
{
// Bind Vertex Buffer
glBindBuffer( GL_ARRAY_BUFFER, gSomeVBO1 );
// Fill in the VAO with our vertex schematic
if( hasShaders )
{
//
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, // Attribute bind location
3, // Data type count
GL_FLOAT, // Data type
GL_FALSE, // Normalise this data types?
sizeof(float) * 5, // Stride to the next vertex
0 ); // Vertex Buffer starting offset
//
glEnableVertexAttribArray( 1 );
glVertexAttribPointer( 1, // Attribute bind location
2, // Data type count
GL_FLOAT, // Data type
GL_FALSE, // Normalise this data types?
sizeof(float) * 5, // Stride to the next vertex
sizeof(float) * 3 ); // Vertex Buffer starting offset
}
else
{
//
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, // Data type count
GL_FLOAT, // Data type
sizeof(float) * 5, // Stride to the next vertex
0 ); // Vertex Buffer starting offset
//
glClientActiveTexture( GL_TEXTURE0 );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, // Data type count
GL_FLOAT, // Data type
sizeof(float) * 5, // Stride to the next vertex
(const GLvoid *)(sizeof(float) * 3) ); // Vertex Buffer starting offset
}
}
// Vertex Buffer 2
{
// Bind Vertex Buffer
glBindBuffer( GL_ARRAY_BUFFER, gSomeVBO2 );
// Fill in the VAO with our vertex schematic
if( hasShaders )
{
glEnableVertexAttribArray( 2 );
glVertexAttribPointer( 2, // Attribute bind location
2, // Data type count
GL_FLOAT, // Data type
GL_FALSE, // Normalise this data types?
sizeof(float) * 2, // Stride to the next vertex
0 ); // Vertex Buffer starting offset
}
else
{
glClientActiveTexture( GL_TEXTURE1 );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, // Data type count
GL_FLOAT, // Data type
sizeof(float) * 2, // Stride to the next vertex
0 ); // Vertex Buffer starting offset
}
}
// Unbind VAO
glBindVertexArrayOES( 0 );
}
In the code above, the first texture coordinate set is interlaced with the position data (offset by the sizeof three floats), and is bound using the first vertex buffer (gSomeVBO1). But the second texture coordinate is contained within a second vertex buffer (gSomeVBO2).
Finally, using the VAO is easy.
//
//
void BindVAO()
{
glBindVertexArrayOES( gVAO );
}
//
//
void UnbindVAO()
{
glBindVertexArrayOES( 0 );
}The call to glBindVertexArrayOES() with the VAO object name is just like calling everything we did in the create function. The only limitation is that one VAO is needed per vertex buffer, even if you have the same vertex schematic.
However, this is a great place for optimisation by sharing the same vertex buffer for vertex data with the same schematic. Then whenever you make a call to glDrawArrays() you can specify which vertex to start from. glDrawElements() is a little more complicated, you will need to increase all your elements in your index buffer so they point to the correct position within the shared buffer.
Or alternatively for glDrawElements(), you could share the same index buffer, and just specify the index buffer offset.
Website Updates
I made some updates to a couple of entries I did a while ago. Fixed an error in my syntax where I calculated the reciprocal, but then divided by the reciprocal instead of multiplying.
I also changed the entries to show equivalent functions instead of my bad descriptions of what the parameters do.
Really bad transistor joke
What did the NPN transistor say when it heard someone whisper 'hey'?
'HELLO!!!!!'
WordPress Category Order
I'm currently doing a general cleanup of the blog this morning. I noticed that WordPress doesn't allow you to order your categories, a quick Google found Category Order which works great, and has a nice Ajax interface.
I've also added some of the iOS apps that I've worked on, it's weird how sometimes I come by stuff in my backup drive that I have just plain forgotten I have worked on.
For example, when i was in Sixth Form I was part of a team that made a robot for fighting in a local event Cyber Scraps (very similar to Robot Wars), setup by the nearby nuclear power plant Sellafield. I can't find any pictures of our robot.
Tap Zoo, the game that punishes you for not playing
I haven't played Tap Zoo for a while, I was hoping I would eventually reach the max level limit to see what happens to the content with these kinds of games, however I eventually gave up, Smurf's I gave up on a few month ago after I missed collecting crops and would have needed to harvest 40+ crops only to replant them.
Tap Zoo I logged back in to find out that it punishes you for not playing. Any animals you were breeding will become sick and the only way to free up the slot is to pay for stars.
Back at the beginning of the game you were given stars on level up, however after about 10 levels that stops. What a bunch of idiots, you do not punish people for coming back to a game, you're suppose to reward them to keep them back.
A recent new called call Tiny Tower is starting to take over the top of the top grossing charts. The reason, in my opinion would be the fact you do not have to pay to gain the ingame bonus tokens, you just need to play.
The more often you play, the faster you will accumulate money, and you gain actual iOS achievement as well.
It also reminds me of SimTower, which is how I came by it in the first place. Just like all these Facebook games, it have little tasks to gain you small amounts of currency as well, delivering people to floors. These not only give you money, but give you people to rent apartments so you can give them jobs.
Occasionally, VIPs will turn up that will knock off time for restocking, building, and increase people arriving at your stores to buy things. As I have said previously, the key to making a successful Facebook game, is to make a game that works like an ordinary game but you do not have to play as well.
EVE Online uses this formula.






