Saturday, November 18, 2017

Coordinate System Conversion Between Unity And A Java Game Server

Requirement from game

For the purpose of FPS attack predication I have to synchronized Hitboxs/BoxColliders between Unity Client And Java Game Server
enter image description here
To be more specific:
  • Each game character is exported to a DAE file for Server and to a FBX file for Client. These files contain geometry, joint and animation information.
  • HitBox information is manually defined and stored as a XML file and shared between Client&Server. Each Hitbox is attached to a Joint/Bone of the corresponding character.
  • When a player shoot a gun, both client and server will need to calculate the hit information. The server do so because it’s the arbitrator. The client do so to predicate the result and response immediately to the player.
The problem becomes complicated when:
  • For some reason we can’t ask unity to do the ray tracing. However there is a shared library between client and server that can calculate whether a bullet ( ray ) has hit a character and the bone being hit if so.
  • Client and server have different Coordinate Systems.
  • When imported to unity, character’s coordinate system is also changed.

Defining Problem

However, if we think about it, we can find the the problem is actually as simple as following:
For each hit box, given the transform (denoted as ) of the joint it attached to in Unity’s coordinate system, we need to find a matrix (denonated as ) that can transform it to the same state in server’s coordinate system.
In the game a character is rotated and translated after animated. Suppose a point has the hierarchy of the following:
- Translate Node
    - Rotate Node 
        - Character Pivot Node
            - Joint1 Node
                - Joint2 Node
                    - Joint3 Node
                        - P
Then in Unity can be defined as:

Where:
  • corresponds to translation
  • corresponds to rotation
  • corresponds to extra rotation introduced while imported by Unity
  • corresponds joint transform
Given we can transform the point from its local space coordinate to its world space coordinate :

Equally, in server we have :

And can use it to transform :

Note that there is a on Unity side, but no on server side. This will be explained latter.
We can easily convert between and and between and , because we know how two coordinate systems are defined. The unknown part is:

That is what Unity do when importing fbx files.

Coordinate Systems

The following image shows two coordinate systems:
enter image description here
Server’s on the left, Unity’s on the right. We can see that Unity’s left handed while server’s right handed. A point in server will be in Unity. The transform matrix would be:


What unity do when importing

After importing a FBX file, we can find that characters has the following changes:
  • If it is originally facing +X axis, it is now facing -X axis. This effectively changes it’s handness
  • It’s pivot is rotated around +x axis for +90 degrees. This step makes it head pointing to up direction again. Here is where the above mentioned comes from.
Given a point , if we change the character from binding pose to another pose, say run, we first transform from its model space to joint local space:

Where:
- is ’s coordinate in character’s binding pose.
- transform a point in joint1’s local space to joint1’s parent’s local space. So will have the reverse effect.
Then we transform to a new model space coordinate.

But if unity negates all model’s x axis. becomes . Suppose there is a matrix does the transform, that is: .
So we have:

Replacing with and with , we have:
$$

$$
For both of the above equations to be true. We can:

That way, the following equation also is true:

Here, stands for a matrix that can transform a point from jointX’s local coordinate to it’s parent’s local coordinate at posture posX.
Having the above information, we can now finish our task. Below is a code snippet of what I have written in our game:
public static Matrix3D Unity2SSJJ(Matrix4x4 result)
    {
        double[] data = new double[16];
        data[4 * 0 + 0] = result.m00;
        data[4 * 1 + 0] = result.m10;
        data[4 * 2 + 0] = result.m20;
        data[4 * 3 + 0] = result.m30;

        data[4 * 0 + 1] = result.m01;
        data[4 * 1 + 1] = result.m11;
        data[4 * 2 + 1] = result.m21;
        data[4 * 3 + 1] = result.m31;

        data[4 * 0 + 2] = result.m02;
        data[4 * 1 + 2] = result.m12;
        data[4 * 2 + 2] = result.m22;
        data[4 * 3 + 2] = result.m32;

        data[4 * 0 + 3] = result.m03;
        data[4 * 1 + 3] = result.m13;
        data[4 * 2 + 3] = result.m23;
        data[4 * 3 + 3] = result.m33;
        return new Matrix3D(data);
    }
    public static Matrix3D TransformToMatrix3D(Transform boneTransform, Matrix4x4 pivotWorldToLoal, PlayerEntity player)
    {
        Matrix4x4 mImportNegX = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, 1));
        Matrix3D m  = Unity2SSJJ(mImportNegX * pivotWorldToLoal * boneTransform.localToWorldMatrix * mImportNegX);
        m.AppendRotation(player.orientation.ViewYaw, Vector3D.Z_AXIS);
        m.AppendTranslation(player.position.Origin.x, player.position.Origin.y, player.position.Origin.z);
        return m;

    }

Saturday, November 04, 2017

Sharing code between CSharp and Java

There are many ways we can share code between C# and Java, for example:

  • Write the shared code in a lightweight scripting language, and run a VM in C# and Java. Lua is one of this type.
  • Write the shared code in a language than can translate both to C# and java, such as Haxe.
  • Write the shared code in Java and use tools to translate to C#.
Sometimes, we already has some existing code in Java, so we are only left with the third option. Besides, even if there is no existing code, Java to C# is an attractive option thanks to Java's rich & friendly development environment.

Recently, I have to share some common logic between Java and C# . To be more specific, there is a Java based game server which are connected by an existing Flash client, what we want to do is to add another Unity client while preserving both Java and AS3's logic.  After a lot of discussion, we decided to adopt the following strategy:

  • First, refactor and extract the shared logic in the Java server to a standalone module which shouldn't be depend on any other java library except Java's buildin library.
  • Second, translated the extracted module from java to C# use a tool such as sharpen.
We choose sharpen as our translating tool, because:
  • first of all, it's open source and can be modified if necessary
  • then, there are some successful application of it already, such as ngit.
There are lots of sharpen version on the internet, and I used the mono version with some multi dimension array fixed from anders9ustafsson's version, and pushed final result to my folk.

The document is very hard to find, so I made a backup in sharpen-doc

Here are some other resources I found usefull:
  • Build help: https://github.com/mono/sharpen
  • Example configuration: https://github.com/ydanila/sharpen_imazen_config
  • Sharpen C# utility classes: https://github.com/mono/ngit/tree/master/Sharpen/Sharpen
  • Another sharpen blog: http://pauldb-blog.tumblr.com/post/14916717048/a-guide-to-sharpen-a-great-tool-for-converting
When running sharpen,do set -Dfile.encoding=UTF-8 option, or some file won't compile successfully.

Command line Arguments:

ArgumentUsage
-pascalCaseConvert Java identifiers to Pascal case
-pascalCase+Convert Java indentifiers and package names (namespaces) to Pascal case
-cpAdds a new entry to classpath:

-srcFolderAdds a new source folder for sharpening
-nativeTypeSystemMap java classes to .NET classes with a similar functionality. For example: java.lang.Class - System.Type
-nativeInterfacesAdds an "I" in front of the interface name
-organizeUsingsAdds "using" for the types used
-fullyQualifyConverts to a fully-qualified name:
-fullyQualify File
-namespaceMappingMaps a java package name to a .NET namespace. For example:
-namespaceMapping com.db4o Db4objects.Db4o
-methodMappingMaps a java method name to a .NET method (can be method in another class). For example:
-methodMapping java.util.Date.getTime Sharpen.Runtime.ToJavaMilliseconds
-typeMappingMaps a java class to .NET type:
-typeMapping com.db4o.Db4o Db4objects.Db4o.Db4oFactory
-propertyMappingMaps a java method to .NET property:
-propertyMapping com.db4odoc.structured.Car.getPilot Pilot
-runtimeTypeNameName of the runtime class. The runtime class provides implementation for methods that don't have a direct mapping or that are simpler to map at the language level than at the sharpen level. For instance: String.substring, String.valueOf, Exception.printStackTrace, etc.
For a complete list of all the method that can be mapped to the runtime class see Configuration#runtimeMethod call hierarchy.
-headerHeader comment to be added to all converted files.
-header config/copyright_comment.txt
-xmldocSpecifies an xml-overlay file, which overrides javadoc documentation for specific classes:
-xmldoc config/sharpen/ApiOverlay.xml
-eventMappingConverts the methods to an event.
-eventAddMappingMarks the method as an event subscription method. Invocations to the method in the form .method() will be replaced by the c# event subscription idiom: +=
-conditionalCompilation
Add a condition when to translate the Java code
- -conditionalCompilation com.db4o.db4ounit.common.cs !SILVERLIGHT
-configurationClassChange the configuration class. The default is 'sharpen.core.DefaultConfiguration'


Annotation Reference:

AnnotationMeaning
@sharpen.enumMark java class to be processed as a .NET enum
@sharpen.renameSpecifies a different name for the converted type, takes a single name argument. For example:
@sharpen.rename Db4oFactory
@sharpen.privateSpecifies that the element must be declared private in the converted file, though it can be not private in the java source:
/*
* @sharpen.private
*/
public List4 _first;
@sharpen.internalSpecifies that the element must be declared internal in the converted file:
/**
 * @sharpen.internal
*/
public abstract int size();
@sharpen.protectedSpecifies that the element must be declared protected in the converted file:
/**
 * @sharpen.protected
*/
public abstract int size();
@sharpen.newAdds the C#-'new' modifier to the translated code.
@sharpen.eventLinks an event to its arguments. For example:
Java:
/**
* @sharpen.event com.db4o.events.QueryEventArgs
*/
public Event4 queryStarted();
is converted to:
public delegate void QueryEventHandler(
  object sender,
  Db4objects.Db4o.Events.QueryEventArgs args);
.......
event Db4objects.Db4o.Events.QueryEventHandler QueryStarted;
@sharpen.event.addMarks the method as an event subscription method. Invocations to the method in the form .method() will be replaced by the c# event subscription idiom: +=
@sharpen.event.onAddValid for event declaration only (SHARPEN_EVENT). Configures the method to be invoked whenever a new event handler is subscribed to the event.
@sharpen.ifAdd #if #endif declaration:
@sharpen.if
@sharpen.propertyConvert a java method as a property:
/**
 * @sharpen.property
*/
public abstract int size();
@sharpen.indexerMarks an element as an indexer property
@sharpen.ignoreSkip the element while converting
@sharpen.ignore.extendsIgnore the extends clause in Java class definition
@sharpen.ignore.implementsIgnore the implements clause in Java class definition
@sharpen.extendsAdds an extends clause to the converted class definition. For example:
Java:
/**
* @sharpen.extends System.Collections.IList
*/
public interface ObjectSet {...
converts to
public interface IObjectSet : System.Collections.IList
@sharpen.partialMarks the converted class as partial
@sharpen.removeMarks a method invocation that should be removed
@sharpen.remove.first
Removes the first line of the method/constructor when converting to C#:
/**
* @sharpen.remove.first
*/
public void doSomething(){
    System.out.println("Java");
    NextMethod();
}
converts to:
public void DoSomething(){
    NextMethod();
}
@sharpen.structMarks class to be converted as c# struct
@sharpen.unwrap
When a method is marked with this annotation
all method calls are removed. This is useful for removing conversion methods when their aren't required in C#.
/*
* @sharpen.unwrap
*/
public Iterable toIterable(Object[] array){
   return Arrays.asList(array);
}
public void doSomething(Object[] objs){
  Iterable iterable = toIterable(objs);
  // do something with the iterable
}
Is converted to:
public IEnumerable ToIterable(object[] array){
    return Arrays.AsList(array);
}
public void doSomething(object[] objs){
   Iterable iterable = objs;
   // do something with the iterable
}
@sharpen.attribute
Adds an attribute to the converted code:
/*
* @sharpen.attribute TheAttribute
*/
public void doSomething(){}
Will be converted to:
[TheAttribute]
public void DoSomething(){}
@sharpen.macroAdd a replace-pattern macro to your code.



Refactoring Legacy Systems

In his book Working Effectively with Legacy Code (Robert C. Martin Series) Robert C. Martin defined legacy systems as systems with no unit testing code.

I have many experiences working with and refactoring legacy systems. Usually, the moment the word "refactoring" pops up in our head, is when the system is too messy and not just without unit testing:

  • The whole system is monolithic. It only can be divided into modules conceptually, but not physically. That is you can never successfully compile part of it separately. 
  • Modules boundaries are blur. No clear responsibility is defined and followed.
  • Dependencies are complex. Singletons are defined and referenced everywhere.  No only they are depended, themselves are dependent on our singletons.
  • ...
In my experience, to successfully refactor a legacy system, I usually go though the following steps:

Refactor building scripts to allow build modules separately. I usually refactor module by module: that is by extracting a cohesive collection of responsibilities into a sub module once at a time. The may depend on other refactored modules, but they should never depend on the monolithic chunk they are originally extracted from. Building modules separately is a good sign of dependency decoupling.

Setup testing environment. The most significant obstacle in refactoring is not that we don't know what's the right thing to do, but that we are afraid that bugs may be introduced. Martin suggest that characterization test code that define existing behavior should be written first. After that we can be more confident when modifying code.

Define and refactor out modules one at a time.  I define modules by their responsibilities. Cohesive responsibilities can be put into one module. Then the real job of code modification begins. Both Robert C. Martin's book and  Martin Fowler and Kent Beck's book gives lots of techniques to show you how to do this.

Write demo programs if unit testing is hard. To be honest, some modules are very hard to unit test, such as 3d rendering related modules. But we can always write some demo programs that uses the module we have just refactored to show that it's self functions is complete and correct.

Some more advice are:
  • Choose a good IDE differs a lot. To be more specific, I strongly recommend Intellij IDEA which I think is a must have tool for me when refactoring.
  •  Decoupling dependency is the most important job. Even if it may introduce some ugly code during the process, you should finish decoupling first. After that, more refactoring is very easy, and that's when you can fix these ugly code introduced earlier.
  • Read Robert C. Martin's book first before you do any refactoring job. It's very practical.

Finding memory leaks in Actionscript programs

It is true that Adobe Flash is dying. In its official blog FLASH & THE FUTURE OF INTERACTIVE CONTENT, Adobe said it will "stop updating and distributing the Flash Player at the end of 2020". But before that happens, we still need to find a way to support our existing AS3 game because millions of players are playing it.

In my experience, AS3 is not a nice programming language. More sadly, it doesn't have very friendly tools to help developing. Flash Builder is buggy when project structure is getting complicated.

And there is no good tool to help find memory leaks in AS3 programs, neither scout nor flash builder. But AS3 is a language that can easy end up with memory leak bugs, due to it's event registration mechanism.

In the end, we have to spend a few weaks to build our own AS3 memory profiling tool.

It has three parts:

  • A apparat based code injection tool named "apparat profiler", which captures all objects that are instantiated.
  • A AS3 library named "profiler.swc" that we can record object when "object instantation" is captured by "apparat profiler". It also is responsible of sending out recorded objects after requested.
  • A MAT based tool we can receive and analysis recorded objects.



There are conditions we need be carefully of:
  • Not all objects are created via AS3 code, so they can't be captured. The walk around is  to run though all recorded objects and see if they have reference to any objects that aren't captured yet.
  • The whole process is slow. But it's ok since finding a memory leak is very hard and more time consuming then without it.

Drawing Git Branch Graphs with gitgraphjs

Recently I have to write a PPT to share with colleages about how to use beyond compare to assist merging. To tell things clearly, I want to draw lots of git branch graphs. Using tools such as Microsoft Visio is one option, but I want a more easy way.

After some searching, I found this amazing tool: http://gitgraphjs.com/. With a few lines of javascript code, it can easily draw the following graph:

It almost satisfies all my needs, except that I want add some identification notes to the nodes, so that I can refer them clearly when presenting.

After some code modification, I successfully added a number to each node, as ire.n the following picture.

The final code is checkin to https://github.com/shawn11ZX/gitgraph.js  and the PPT is shared at slideshare


Sunday, February 12, 2017

Reading Notes: How to Read a Book

How to Read a Book is written by the American philosopher Mortimer J. Adler. It can be classified into the category of Practical Books.
In a nutshell, this book tries to help improve people’s ability of reading books. It states that before reading any book there are four questions each reader must ask themselves:
  • What is the book about as a whole
  • What is been said in detail and how
  • Is the book true, in whole and part
  • How is the book related to you?
By dividing people’s ability of reading into the following four different but highly related levels, the author helps us find ways as to how to answer the above four questions.
  • elementary reading
  • inspectional reading
  • analytical reading
  • syntopical reading
The book is consists of four parts with each part have several chapters.

1. PART ONE: THE DIMENSIONS OF READING.

Given the same book, different reader can have very different gains. The difference is mainly caused by reader’s active attitudes and reading skills. The more effort we put on reading the more understanding we can obtain from it.
There are four levels of reading, each lower level is included in higher level. That is the higher the level one is choosing, the more effort he will need to pay, and finally the more comprehension he can get from the reading activity.

1.1. elementary reading

The first and lowest level of reading is elementary reading. The purpose of this level is answer the question: What is the meaning of the sentences. This level can be further divided into four stages:
  1. reading readiness, corresponding to pre-school experiences.
  2. word mastery
  3. vocabulary growth and utilization of context
  4. functional literacy.
At the final stage, children can read traffic signs or picture captions fairly easy. They are considered mature readers and can almost read any kinds of books.

1.2. inspectional reading

The second level of reading is inspectional reading, which answers the question: what the book is about as a whole. It can be divided into two steps:
Step one is systematic skimming or pre-reading. By going through title, preface, table of content, index, publisher’s blurb, and some intentionally chosen chapters or paragraphs one can get a brief impression of the book and be able to classify it. We should consider ourselves as detectives looking for clues to a book’s general theme or idea.
Step two is superficial reading. The trick is to read from front to end with as little pause as possible, without looking up dictionaries, encyclopedia or thing alike. As the author said, trying to understand every detail at this stage can easily destroy your interest and curiosity in this book. Even if you are not going to read it again, reading a whole book without total understanding is better than never read it through.

1.3. Demanding Readers

To be good at reading, one need to be active. To be active, the trick is to first ask the above mentioned four questions and then find answers as you read.
During reading, we can also make marks on the book to:
  • keep us awake
  • help us clearly express our understanding and ideas
  • help us remember author’s ideas.
The person who says he knows what he thinks but cannot express it usually does not know what he thinks.

2. PART TWO: Analytical reading

Analytical reading contains three phases, each of which emphasizes several rules.
  • Phase 1 answers the question "What is the book about as a whole"
    • Rule #1: Classify a Book
    • Rule #2: Summarize the content of the book with one sentence
    • Rule #3: List the outline of the book
    • Rule #4: Find out the questions the author tries to answer in the book
  • Phase 2 answers the question "What is been said in detail and how"
    • Rule #5: For keywords, find out the exact definition
    • Rule #6: Find out key proposals that result in the main idea of the book
    • Rule #7: Figure out how these proposals are proven in the book.
    • Rule #8: Of the questions in Rule #4, make clear what of these are answered and what are not. Of the unanswered questions, what are recognized by the author.
  • Phase 3 answers the 3rd one by making remarks about the book
    • Rule #9: Fully understand the book before making any judgement.
    • Rule #10: Don’t be aggressive
    • Rule #11: Differentiate between knowledge and opinion before remarking
If you want to make criticisms:
  • Rule #12: prove that the author’s knowledge is not adequate
  • Rule #13: prove that the author’s knowledge is wrong
  • Rule #13: prove that the author is illogical
  • Rule #13: prove that the author’s analysis or reasoning is inadequate

2.1. Classifying a Book

The first step of analytical reading is find the category of the book you are about to read, the earlier the better.
Books can be first classified into two categories: expository or fiction. The purpose of expository book is to convey knowledge.
We may or may not find hinds about a book’s category from its title.
Expository books can be further split into two kinds: practical and theoretical. The former focuses on HOW, while the later concentrates on WHAT.
Examples of practical books include:
  • engineering
  • medical
  • cooking
Not only do practical books tells us HOW, they usually spend a lot of effort persuade us to follow their instructions. After all, a practical book that is not followed by its readers is actually mean-less.
Common words in practical books includes: should, ought, good or bad.
Examples of theoretical books include:
  • history, describes true events happened at specific locations in specific time periods.
  • science, which is about general truth, most of which can’t be easily verified in our daily life but rather based on accurate observations or experiments.
  • philosophy, which can’t usually drift too far away from our daily experiences.

2.2. Questions of the author

At the beginning of writing, writers usually has one or more questions, which they answer in the book.
For practical books, questions may be like:
  • What ends should be sought?
  • What means should be chosen to a given end?
  • Under given conditions, what’s better? what’s right? what’s worse?
For theoretical books, these are example questions:
  • Does something exist?
  • What kind of thing is it?
  • What’s the effect?

2.3. Keywords

No language is perfect. Every words can have several meanings and every meaning can be conveied by more than one word. That why we need to reach a common defination of the keywords in the book with the author.
Personally, that’s why I find it’s sometimes more easy to read the original version of a book even if it’s written in a foreign langure, than to read a translated book in my native language. Because during translation, if the translators are a little careless, meanings of keywords will be mistranslated.

3. PART THREE: syntopical reading

Synotopical reading is usually applied to reading of social science books. Since it’s relatively hard to find a main authentic book of a given subject, we need to read and compare several books to understand the subject.