Mar 13, 2017

Entanglement

Entanglement?

Some time ago there was a game popular over there, called Entanglement:

There are a few implementations of this game under Android:

But there was no such game for iOS. And as I pursued my second M. Sc. degree, I have had a course “iOS development”, where we were learning to use Swift and iOS platform.

I decided to implement this game as my course project. In Swift. Originally the game was implemented in Swift 2 (there was no Swift 3 back those days).

And recently I decided to refactor the game a bit and update it to the most recent Swift version (which is Swift 3 at the moment of writing this post).

In this post I’ll describe some interesting decisions I made while creating this game.

libc.js

Recently I’ve written a post about functional programming techniques, coming into the world of front-end and the library I crafted as an experiment. That library, libc.js was highly inspired by Elm and Mithril. But it suffered two major features:

  1. components were hardly able to be used in other components
  2. the interaction between components was nearly impossible (or, at least, not very transparent)

What’s hidden beneath the next version of the library?

Have you ever asked anyone if assembly language might be useful nowadays? So, here’s the short answer: YES. When you know how your computer works (not a processor itself, but the whole thing - memory organization, math co-processor and others), you may optimize your code while writing it. In this short article, I shall try to show you some use cases of optimizations, which you may incorporate with the usage of low-level programming.

Recently I was reading through my old posts and found out there is a gap in the article about SSE - the post did not cover some of the implementation caveats. I decided to fulfill this and re-publish a new version.

Feb 18, 2017

Functional web

In last couple of years the functional programming paradigm became very popular. A huge amount of libraries, tools, tutorials and blog posts appeared. Although the paradigm itself is rather old (lambda calculus was developed around 1930 and the Lisp language was introduced in 1950), its popularity blew up rapidly somewhere in 2014-2016 and that’s what is happening right now. Probably one of the most powerful influencers, giving FP (functional programming) that thrust is web development. Since Facebook introduced React, the community started incorporating many things from FP with React - including Redux and Immutable.js. But there are much more interesting things which were invented on this wave of FP popularity. One of them is Elm.

This is a story how I implemented invented yet another web framework wheel.

Dec 21, 2016

Clojure guards

Once I wanted to have something like a pretty “match” operator from Scala, but in Clojure. And hence there are no default options for it in Clojure out of the box, here are some alternatives I’ve found in the Internet.

Aug 25, 2016

Big O notation

The best big O notation explanation I’ve ever saw I’ve found on… Google Play Market! I was hanging around, looking for the suggested software and, for some reason, I’ve decided to install some educational application for programmers. And here’s what I’ve found…

This is a chicken. This 3D model I’ve made in 3.5 hrs in Blender (with texturing).

Taking into account the fact I’ve started learning Unity 3D, I will possibly use this in the remake of my old Shoot Them! game. Like this (early preview, made with Unity 3D in ~3 hrs):

Foreword

In this section we will implement the communication layer for our application. It’ll handle all the requests to/from our web server. Have no worries - we will create server application in the next section!

First resource

Let’s create a Session resource. Since we have no backend part, we should stub the data. We’ll use Angular Services. That’s easy: a service defines a function, returning, say, an object. That object will be used every time you call a service. And you may use not only objects - you may return functions, constants or literally anything from your services.

General architecture

The first thing we need to think of is how we’ll be gathering the information about users. It’s quite easy - we just need to get a request from a visitor. Of any kind - it may be a request to get an image, a file, a stylesheet or a script.

Then we’ll just parse headers from that request and save the extracted data in the database. The only problem here is: how to get unique key from each request?. We may use visitor’s IP address. It’s the easiest way.

If you remember, we ended our coding excercises at place, where we almost created our first Newtonian body, but we did not actually have enough models.

We discussed collision shapes a bit. So let’s create one for our brand new model!

We have a nice ramp to work with. But how we can reconstruct the same shape in the terms of Newton? Newton offers a set of collision shapes for us:

  • Sphere

    Sphere

  • Box

    Box

  • Cone

    Cone

  • Capsule

    Capsule

  • Cylinder

    Cylinder

  • Chamfer Cylinder

    Chamfer Cylinder

  • Convex Hull

    Convex Hull

  • Trimesh

    Trimesh

Obviously, not sphere, cone, capsule, nor cylinder make sense for us. We could use box shape, but then we simply ignore our inner faces (inside walls):

Box collision shape for our ramp

A bit better, but still the same situation with convex hull shape:

Convex hull collision shape for our ramp

Generally, the way we create our Newtonian body is:

  1. create collision shape
  2. create blank Newtonian body
  3. set body properties like collision shape, mass, inertia parameters, etc.
  4. store the pointer to the graphical entity for that body in the userData property

And then Newton Game Dynamics will take your body into account when processing other objects in the NewtonWorld.

Tree mesh collision shape

So we gonna use the triangle mesh shape. What we gonna do is loop through all the triangles of our mesh and build its copy, but in the world of “physic” bodies.

To loop through all the triangles, we need to take each 3 edges of our mesh and the corresponding vertices (because each edge is represented by two its vertices - their indexes in the list of vertices) and create Newtonian triangle. Irrlicht stores vertices in one of three formats:

  1. plain vertex, represented by its three coordinates; the irr::video::S3DVertex class in Irrlicht
  2. vertex with texture coordinates; irr::video::S3DVertex2TCoords class
  3. vertex with its tangent information; irr::video::S3DVertexTangents class

All those are represented by irr::video::S3DVertex class or its children. Moreover, we do not need nothing but the information on vertex’ coordinates in our case, so we may use only the base class’ properties.

The code, creating trimesh collision shape is quite simple and straightforward:

void createTrimeshShape(irr::scene::IMeshBuffer *meshBuffer, NewtonCollision *treeCollision,
                                     irr::core::vector3df scale = irr::core::vector3df(1, 1, 1)) {
    irr::core::vector3df vArray[3];

    irr::video::S3DVertex *mb_vertices = (irr::video::S3DVertex *) meshBuffer->getVertices();

    u16 *mb_indices = meshBuffer->getIndices();

    for (unsigned int j = 0; j < meshBuffer->getIndexCount(); j += 3) {
        int v1i = mb_indices[j + 0];
        int v2i = mb_indices[j + 1];
        int v3i = mb_indices[j + 2];

        vArray[0] = mb_vertices[v1i].Pos * scale.X;
        vArray[1] = mb_vertices[v2i].Pos * scale.Y;
        vArray[2] = mb_vertices[v3i].Pos * scale.Z;

        NewtonTreeCollisionAddFace(treeCollision, 3, &vArray[0].X, sizeof(irr::core::vector3df), 1);
    }
}

We take the edges (indices), find their vertices, create a triangle - and we’re done! You may have noticed, we do not actually create the collision shape here - we take it as an argument for our function. You will see why this is done that way in a moment.

Now it’s body’s turn! But we need to extend our Entity class with the NewtonBody field so that we can seamlesly integrate it to our engine:

class Entity {
private:
    scene::ISceneNode *mNode;
    NewtonBody *mBody;

public:
    Entity(scene::ISceneNode *node) : mNode(node), mBody(0) { }

    Entity(scene::ISceneNode *node, NewtonBody *body) : mNode(node), mBody(body) { }

    scene::ISceneNode *getSceneNode() const {
        return mNode;
    }

    NewtonBody *getBody() const {
        return mBody;
    }

    void setBody(NewtonBody *body) {
        mBody = body;
    }
};

And now we are ready to set our NewtonBody:

void createMeshBody(const std::string name) {
    Entity *entity = entities[name];
    irr::scene::IMeshSceneNode *node = (irr::scene::IMeshSceneNode *) entity->getSceneNode();

    NewtonCollision *shape = NewtonCreateTreeCollision(newtonWorld, 0);
    NewtonTreeCollisionBeginBuild(shape);

    irr::scene::IMesh *mesh = node->getMesh();

    for (unsigned int i = 0; i < mesh->getMeshBufferCount(); i++) {
        irr::scene::IMeshBuffer *mb = mesh->getMeshBuffer(i);
        createTrimeshShape(mb, shape, node->getScale());
    }

    NewtonTreeCollisionEndBuild(shape, 1);

    float mass = 0.0f;

    dMatrix origin;
    NewtonCollisionGetMatrix(shape, &origin[0][0]);
    NewtonBody *body = NewtonCreateDynamicBody(newtonWorld, shape, &origin[0][0]);

    dVector inertia;
    NewtonConvexCollisionCalculateInertialMatrix(shape, &inertia[0], &origin[0][0]);
    NewtonBodySetMassMatrix(body, mass, mass * inertia.m_x, mass * inertia.m_y, mass * inertia.m_z);
    NewtonBodySetCentreOfMass(body, &origin[0][0]);

    NewtonDestroyCollision(shape);

    NewtonBodySetTransformCallback(body, transformCallback);
    NewtonBodySetForceAndTorqueCallback(body, applyForceAndTorqueCallback);

    NewtonBodySetUserData(body, entity);
    NewtonInvalidateCache(newtonWorld);

    entity->setBody(body);
}

There is an interesting piece here, though: we used recursion to create collision shape… But if you remember, we did not create collision shape with our createTrimeshShape method - all we do in that method is that we add new triangles to the existing shape. That’s because meshes in Irrlicht are stored as a tree structure - they may have sub-meshes, which are still parts of the whole mesh. And they can have their sub-meshes too. So we created a blank collision shape and fill it with new parts of the mesh.

Doing it that way prevents us from overcomplicating the task and building a composite mesh, made of a set of trimeshes. That would be really hard to calculate in real-time! And our really simple scene would work with the speed of 5x5 battle in Unreal Tournament 3…

Looking back to our list, we should now fill out all the fields for our NewtonBody. And since we are making the static model, we will set its mass to zero. This is enough for Newton to treat our body as the static one. I placed the other code to show the other fields, we need to fill in case we have a “usual” body.

So the other fields of NewtonBody are:

  1. massMatrix, which determines how the mass is spread along the body
  2. transformCallback and forceAndTorqueCallback are two mandatory fields, required by Newton
  3. userData, which will hold the pointer to the whole entity

massMatrix could be calculated automatically from the collision shape, like in our case. Without digging much into details, we will simply set it so the mass of our body is distributed uniformely.

transformCallback is the function, which will be called for our body each time it changes its position due to the interaction with other bodies inside NewtonWorld.

forceAndTorqueCallback is the function, which applies forces and torques to our body. This is a bit tricky, but you need to keep track of each force and torque by yourself and then apply them in a way that they summ up and create the final force, influencing the body. We will talk about it later, when we will deal with impulses.

So, the transformCallback:

static void transformCallback(const NewtonBody *body, const dFloat *matrix, int threadIndex) {
    Entity *entity = (Entity *) NewtonBodyGetUserData(body);
    scene::ISceneNode *node = entity->getSceneNode();

    if (!node)
        return;

    core::matrix4 transform;
    transform.setM(matrix);

    node->setPosition(transform.getTranslation());
    node->setRotation(transform.getRotationDegrees());
}

Nothing tricky here.

To put everything in place, let’s add a sphere to our scene. The process is totally same, except of the collision shape creation - in case of primitives like box, sphere or cylinder, it is much more easy than with trimeshes - you do not need to loop through any indices or vertices - just set shape params like dimensions or radius. And body creation process is totally same.

void createSphereNode(const std::string name, const std::string textureFile) {
    scene::ISceneNode *node = smgr->addSphereSceneNode();

    if (node) {
        node->setMaterialTexture(0, driver->getTexture(textureFile.c_str()));
        node->setMaterialFlag(video::EMF_LIGHTING, false);
    }

    entities[name] = new Entity(node);
}

NewtonCollision *createSphereCollisionShape(scene::ISceneNode *node, float radius) {
    dQuaternion q(node->getRotation().X, node->getRotation().Y, node->getRotation().Z, 1.f);
    dVector v(node->getPosition().X, node->getPosition().Y, node->getPosition().Z);
    dMatrix origin(q, v);

    int shapeId = 0;

    return NewtonCreateSphere(newtonWorld, radius, shapeId, &origin[0][0]);
}

void createSphereBody(const std::string name, float radius, float mass) {
    Entity *entity = entities[name];
    scene::ISceneNode *node = entity->getSceneNode();

    dQuaternion q(node->getRotation().X, node->getRotation().Y, node->getRotation().Z, 1.f);
    dVector v(node->getPosition().X, node->getPosition().Y, node->getPosition().Z);
    dMatrix origin(q, v);

    int shapeId = 0;

    NewtonCollision *shape = NewtonCreateSphere(newtonWorld, radius, shapeId, &origin[0][0]);

    dMatrix origin;
    NewtonCollisionGetMatrix(shape, &origin[0][0]);
    NewtonBody *body = NewtonCreateDynamicBody(newtonWorld, shape, &origin[0][0]);

    dVector inertia;
    NewtonConvexCollisionCalculateInertialMatrix(shape, &inertia[0], &origin[0][0]);
    NewtonBodySetMassMatrix(body, mass, mass * inertia.m_x, mass * inertia.m_y, mass * inertia.m_z);
    NewtonBodySetCentreOfMass(body, &origin[0][0]);

    NewtonDestroyCollision(shape);

    NewtonBodySetTransformCallback(body, transformCallback);
    NewtonBodySetForceAndTorqueCallback(body, applyForceAndTorqueCallback);

    NewtonBodySetUserData(body, entity);
    NewtonInvalidateCache(newtonWorld);

    entity->setBody(body);
}

Have no fear about code duplication - we will remove it later. When you are done, you should get picture like this one:

First completed dynamic scene

Congrats! That’s our first completed dynamic scene!