Sunday, 25 April 2010

On Hold For a Bit

Hello .... Yes I know its been a few months since my last post. The project is still live, but due to work commitments and urgent contracts I have had to put the Globe application on hold.
I will turn my attention back to this is the very near future.

Monday, 25 January 2010

Its Time For Chat

Well now the networking system is in, the first thing I wanted to turn to my attention to is a chat system.

Before I began creating GUI design for chatting, I started thinking back to some Second Life features. The ability to take a snapshot of the current view, without any interface components cluttering up the shot. The snapshot would have to be taken at the exact moment after the world display had finished rendering, but before any GUI elements had begun rendering.

With this in mind, I decided I needed one main UI manager class to handle all child overlay components, such as menu bar, task bar, chat bar and whatever else comes up in the future, to keep things clean and easy to manage.

I created a design I am happy with for the task bar and chat bar and their relevant classes and I created the UiManager class.

I am currently working on these components. That is my update. :)

Another post to follow ...

Saturday, 23 January 2010

The Network Is In ...

I have spent most of the day today working on the Globe servers and client integration.

Due to the need for the simulator server to run over UDP, some changes had to be made to the different servers roles. The login server now returns an asset server address and port as well as a simulator address and port on successful login. The simulator server currently only serves the time at 100ms intervals, but will shortly serve chat and avatar positions. The asset server is now responsible for returning asset keys which the simulator was previously responsible for, as well as the actual assets themselves in binary form.

Basic UDP is now implemented in the simulator and client, and I have added multithreading to the login client implementation for a smoother user experience.

The base of the networking code is now complete, and if I decide a more advanced UDP method is more appropriate in future, the simulator code is nicely separated and shouldn't be a problem to change.

I have changed the Globe system to work from domain names rather than IPs because this is a more flexible approach. I have set up temporary sub domains and configured my router to allow access to the servers from outside my network.

The next steps are slightly more fun, in creating the temporary avatars and chat functionality.
I have had an idea for the avatar design, so if I get time tomorrow I would like to have another go at that. The 3D company I contacted, turned out to be no good.

The client C++ project structure is shown below.





























Below are the Simulator and Asset servers running in their console form.



I will post an update of my progress tomorrow ....


Thursday, 21 January 2010

UDP is a different animal to TCP

This post is all about how Globe is going to work or is working from a networking perspective.
Firstly I'll explain a bit about TCP and UDP sockets.

TCP
Transmission Control Protocol is a connection based protocol, so the client makes a direct connection with the server, data is sent and received and when everything is complete the socket is disconnected.

UDP
User Datagram Protocol is a connectionless packet based protocol, so no connection between client and server is made, instead packets are created and sent across networks via routers. UDP is an unreliable protocol, as in there is no guarantee the data will arrive at its destination and in the same order it was sent. Because the protocol is connectionless, it has much less overhead and is far more efficient than TCP at transferring data.

UDP also comes with some interesting features that I am still in the process of researching.

Multicasting
A server creates a multicasting group, clients join the group which acts as an end point, the server sends streaming data once to the group and it is automatically duplicated and distributed to client group members as required by the network. There isn't a more efficient way to send data across a network than this, and recently BT has talked of plans to unveil HDTV over this kind of connection, which shows the kind of data transfer possible.
I am not sure of ISP support of multicasting or what is involved yet, so more to come on this when I find out.

Unicasting
Still researching this one.

Broadcasting
I have found with broadcasting, unlike multicasting, everyone in range of the server receives the packet, not just clients subscribed to a group. From what I have read this is only really useful in a LAN environment, so I won't be researching this any further.

As you know, there are 3 types of server to the Globe system.
Login Server
Asset Server
Simulator Server

All 3 servers were originally implemented with TCP sockets. The login and asset server will stay as TCP, but the simulator needs constant fast data transfer, so it is moving to UDP.

What flavour of UDP depends on my research.

The plan is to get the UDP implemented in the simulator server at the same time as the temporary box avatar, so that features can be developed such positioning of other nearby avatars and chat.

I looked at the Enet network library in a bit more detail and it seems they have devised a wrapper for UDP to guarantee delivery of packets in the right order, so this is still a strong contender. Again, needs more research.

I'll keep ya posted.

Wednesday, 20 January 2010

You could spend years learning that!

I have spent a couple of days working on character modelling in various 3D designers, including Poser 6, MilkShape 3D, Character FX, LithUnwrap and various other tools.

I know how to operate these tools and I can create basic models, but detailed, optimized and animated 3D characters is out of my league right now. I will continue to learn how to do it, but I think it is something that can take years to master, and I need avatars now.

My plan is to stop working with the 3D modellers and go back to the Globe code.

For now, an avatar will be represented by a human sized box, this way the project can still move forward whilst a solution is found to the avatar design problem.

I have contacted a 3D design company to enquire on costs of outsourcing the character design to them. I have a feeling it will be out of my price range, but its worth a try.

I have a couple of other ideas up my sleeve. I'll keep you posted.


Tuesday, 19 January 2010

Terrain, Bones and Avatars

Here I am again, it has been a few days since my last post and although I have still been working on Globe, not as much code has been written as in previous posts.

After my last update we had a skybox being rendered, some basic UI elements and asset and simulator server connectivity and data transfer.

My next step was to improve some of the the features I had already created, such as the camera controls. I came up with a mouse collision detection algorithm which provided pixel perfect mouse click collision detection with the control buttons. This was harder than it sounds because the buttons are a kind of cone shape. I also improved the camera rotation and positioning based on input from the camera control.

I improved the simulator server process, so it stays connected and constantly pumps data across, but having done a bit more research I will be switching this from TCP to UDP for performance reasons and broadcast features, so the code will need to change again. At this point I am thinking I will do this with native C socket functions, but I am also considering ENet which is a UDP networking library. http://enet.bespin.org/index.html

I added a terrain table to SQL and some data layer classes and wrote the code required for the simulator to serve the terrain data. The terrain requires 3 images to work. The heightmap, which defines the height of each face on the land. The terrain texture which is stretched over the entire landscape. The detail map, which is repeated many times over the landscape to create the effect of surface texture. So now terrain is being rendered.

As really the whole experience of a virtual world is based around the users avatar, I decided this was the next stop, the notorious time consuming character modelling and animation and the reason less code has been written this time around.

The Irrlicht 3D engine I am using for this project can handle 2 types of character animation, Morph Target and Skeletal animation. As we want maximum flexibility in allowing users to upload their own animations, this rules out Morph Target animation, we have to go down the skeletal route, so that animations can be applied to the bones instead of needing to rework the entire model for each individual animation. Irrlicht natively supports 3 skeletal animation file formats, .ms3d (Milkshape 3D), .b3d (Blitz 3D) and .x (DirectX).

I decided to go with Milkshape 3D files as the software is relatively inexpensive and easy to use and is packed with features.

So I set off on my mission of learning to model in MilkShape. I created several models to learn the interface and ways of doing things. I have used 3D Studio Max quite a bit, so that helped me pick it up quickly. When I was sure I had got to grips with it, I started creating a male human character. I hit a few problems with disconnected vertices and broken texture mapping, but by version 4 I had a nice looking nearly finished male avatar.

Tonight I plan to do the finishing touches on the male avatar model, and texture him with a default skin. The next steps will be to create a skeleton for him and a basic stand and walk animation.

When I have an avatar model ready, I will concentrate on creating the code necessary to serve it from the servers and render and control it in-world, and then simulator UDP networking support for other avatar positions and chat.

I'll post an update soon ...

Friday, 15 January 2010

We have a world!

I haven't blogged in a few days because of the sickness, but I have made some more progress on the Globe system, so here goes ...

At the end of my last post I had the Simulator server in a state where it could be connected to, it would return information about the skybox, and an IP and port of its primary asset server. The asset server was in a state where it could serve textures across TCP.

No socket code was implemented in the client at that point to support any of this.

Present day ...

The client can now login, display a loading screen whilst it connects to the Simulator, gets the initialization data, checks which assets it already has in its cache, and downloads any missing textures etc. from the asset server. When its happy it has everything it needs to start, the loading screen disappears and it renders the skybox that has just come from the servers and some basic GUI.

But what a journey it was to get there, I have hit some really nasty problems along the way. Read on ...

My first hurdle was threading. My implementation of the sockets code was not asynchronous, so the animation on the loading screen would stop whilst everything loaded. Not good. As a C# developer I would think, no problem, the Thread class can sort that out. But in C++ things are not quite so straight forward.

As I read through forum post upon forum post, it became more obvious that threading is not supported in C++. It is only possible through functionality in old C libraries. ... Gulp.

I eventually came across this great article by Arun N Kumar, which solved the problem.
The class he has developed there wraps the C functionality into an inheritable C++ class. Using his code as guidance I successfully created a C++ thread class for use in the Globe client.

Perfect, so now we have threaded sockets in the client application, I could pass a login token into the thread and it would go off and connect to its servers asynchronously allowing the loading animations to carry on doing their thing.

Next I need to get data returned from the servers out of the threads in its object form, which could be a few different class types, but I am already using the thread argument as a pointer to the login token and accessing class members from inside the thread produces access violations.

This was a hard one. After about 12 hours I found a solution.
  • I created a 4k (void*) buffer in memory before the thread was called.
  • The login token is serialized into that buffer, with a 4 byte DWORD value indicating the size of the class it contains, and then the thread is started.
  • The pointer to the buffer is passed into the thread as the argument.
  • The thread carries out its tasks, and loads data into the buffer, along with its class size.
  • The main thread checks the buffer to see what type of data it has based on its size.
  • When the size matching the correct class is found it knows the data is ready and retrieves it.
The next problem I came across was that the textures the asset server was sending were becoming corrupt when they arrived in the client cache. I checked everything I could think of, the files were being written as binary, the data was coming across correctly.

I eventually opened the downloaded JPG in a hex editor, and compared the original. I realized the downloaded one had no zeros in it, they had been stripped at some point in the process. On closer inspection of the code, the client was loading the file into a irr::core::stringc object before it was saved, this was the cause. I loaded it into a standard buffer and it started working fine.

Great free hex editor.

These were the main problems I hit, there has been times I have had to walk away from the screen because I find myself getting nowhere. Its always good to take a break when you think you have hit a problem you will never solve. Everything is solvable. Sometimes you can save hours of pain with a 30 minute break.

After getting over the nightmare communicating asynchronously with the servers, I quickly implemented a skybox based on the data we have received and started to render it.

The next thing was to create some way of the user controlling the camera. In Second Life, there is a nice camera control, a small widget that sits usually at the top of the screen allowing you to rotate and move the camera around (known as caming in-world). It's a UI element, that takes a small amount of getting used to, but people become familiar with it, so I decided to create something similar.

I created a nice menu system, similar to the standard Windows one, but of course much better looking. :) The main headers at present are File, Edit, Window. File contains Upload and Exit, Edit contains Preferences and Window contains Camera Control. The system is very scalable to allow new menus and items to easily be added. I plan to add a server authenticated Admin menu in the near future.

You can now move the camera around with the Camera Control, but the positioning algorithm is not yet perfect, I am now working on that.

So .... essentially, Globe's first sim exists, so we have a virtual world!