Skip to main content

News

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Flying Jester

1
Programming / Colliding a Sphere with a Plane
No pun intended :P

I want to post how this is (easily) done, since I can't find any useful examples online. I keep needing this on and off over the years, so I might was well give it a home here.

It's actually super easy to do, but there are very few discussions of such. It's also the same as checking the distance between a point and a plane (since a sphere is just a point and a distance).

First, take a three points to define the plane and determine the normal to the plane using these points.

For reference:
Code: (javascript) [Select]

function cross(a, b){
  let x = (a.y * b.z) - (a.z * b.y);
  let y = (a.z * b.x) - (a.x * b.z);
  let z = (a.x * b.y) - (a.y * b.x);
  return {"x":x, "y":y, "z":z};
}

function subtract(a, b){
  return {"x":a.x - b.x, "y":a.y - b.y, "z":a.z - b.z};
}

function normal(a, b, c){
  let da =  subtract(a, c);
  let db =  subtract(b, c);
  return cross(da, db);
}


Then, determine the plane's D component which is negative of the normal multiplied by one of the points.

Code: (javascript) [Select]

function multiply(a, b){
  return {"x":a.x * b.x, "y":a.y * b.y, "z":a.z * b.z};
}

function plane_d(normal_cmp, point){
  let d_vec = subtract({"x":0, "y":0, "z":0}, multiply(normal_cmp, point));
  return d_vec.x + d_vec.y + d_vec.z;
}


So, to create a plane (we will want the normal vector to be normalized for later):
Code: (javascript) [Select]

function normalize(vec){
  let m = Math.sqrt((vec.x * vec.x) + (vec.y * vec.y) + (vec.z * vec.z));
  return { "x":vec.x/m, "y":vec.y/m, "z":vec.z/m };
}

function plane(a, b, c){
  this.points = [a, b, c]; // It will be useful to know at least one point on the plane later.
  this.normal = normalize(normal(a, b, c));
  this.d = plane_d(this.normal, a);
}


Alright, so the very obvious part. We need to collide a line that passes through the sphere's center, from the points on the sphere's edge that are exactly the radius away in both the plane's normal and anti-normal (aka, a line going all the way through the sphere, crossing the center, and perpendicular to the plane).

Then, we generate a 3x3 matrix from this and the difference of the three points we defined the plane from (any three points on the plane would work, but here we already have some). Then, invert the matrix and multiply that by the matrix [ line.x-points[0].x, line.y - points[0].y, line.z - points[0].z ] (but in column order).

Code: (javascript) [Select]

    /*
     *   [ a b c ]          [ A D G ]          [  (ei-fh) -(bi-ch)  (bf-ce) ]
     * P [ d e f ] = det(A) [ B E H ] = det(A) [ -(di-fg)  (ai-cg) -(af-cd) ]
     *   [ g h i ]          [ C F I ]          [  (dh-eg) -(ab-bg)  (ae-bd) ]
     * For the line of points A and B and the plane of points 0, 1, 2
     *        [  (ei-fh) -(bi-ch)  (bf-ce) ] | [ (Xa-Xb) (X1-X0) (X2-X0) ]
     * det(A) [ -(di-fg)  (ai-cg) -(af-cd) ] | [ (Ya-Yb) (Y1-Y0) (Y2-Y0) ] = W
     *        [  (dh-eg) -(ab-bg)  (ae-bd) ] | [ (Za-Zb) (Z1-Z0) (Z2-Z0) ]
     *
     * det(A) = 1/(a * A + b * B + c * C)
     * det(A) = 1/((Xa-Xb) * (ei-fh) + (X1-X0) * (ch-bi) + (X2-X0) * (bf-ce))
     *                   [ Xa-X0 ]   [ T ]
     * Thus, inverse W * [ Ya-Y0 ] = [ U ]
     *                   [ Za-Z0 ]   [ V ]
     * T is between 0 and 1 if the intersection is along the line.
     * (U+V) <= 1 if the intersection is withing the three points.
     */
plane.prototype.whyareyoudoingthistome = function(sphere){
  line = {"x1":sphere.x + this.normal.x * sphere.radius, "y1":sphere.y + this.normal.y * sphere.radius, "z1":sphere.z + this.normal.z * sphere.radius,
    "x2":sphere.x - this.normal.x * sphere.radius, "y2":sphere.y - this.normal.y * sphere.radius, "z2":sphere.z - this.normal.z * sphere.radius};
  let a = line.x1 - line.x2, b = this.points[1].x - this.points[0].x, c = this.points[2].x - this.points[0].x,
    d = line.y1 - line.y2, e = this.points[1].y - this.points[0].y, f = this.points[2].y - this.points[0].y,
    g = line.z1 - line.z2, e = this.points[1].z - this.points[0].z, f = this.points[2].z - this.points[0].z;

  // The commented out portions would only be useful if we wanted to determine if the intersection was bound by the three input points.
  let A = ((e*i)-(f*h)), B = ((c*h)-(b*i)), C = ((b*f)-(c*e)),
    D = ((f*g)-(d*i)),/* E = ((a*i)-(c*g)), F = ((c*d)-(a*f)), */
    G = ((d*h)-(e*g)) /* H = ((b*g)-(a*b)), I = ((a*e)-(b*d)) */ ;
  let Q = line.x1 - this.points[0].x, R = line.y1 - this.points[0].y, S = line.z1 - this.points[0].z;
 
  // Inversion coefficient, of course. Mismatched to match the final matrix rotation for inversion.
  let det = 1 / ((a*A) + (b*D) + (c*G));
  let T = ((A*Q)+(B*R)+(C*S)) * det;

  // U and V are UV coordinates on the triangle along which we intersected. If you were ray-tracing, for instance, this would be texture coordinates relative to the intersection.
  // let U = (float)((D*R)+(E*S)+(F*T)) * det_a;
  // let V = (float)((G*R)+(H*S)+(I*T)) * det_a;
 
  // T is actually the T position along the line where the plane and the line intersect.
  return T >= 0 && T <= 1;
}


So obvious, so clear.

Except this is actually the really hard way. I've done it this way for some years, but today I made a discovery that made me feel like an idiot.

Are you ready for it?

Here is the easy way

The D coordinate of the plane's equation, if the normal vector has been normalized before D was calculated, is the distance from the point to the plane.

Code: (javascript) [Select]

plane.prototype.collideSphere(sphere){
  let point = multiply(sphere, this.normal);
  let distance1 = point.x + point.y + point.z + this.d;
  return Math.abs(distance1 ) < sphere.radius;
}


...

Sometimes I feel that my calculus classes in college let me down me in some ways.
2
Off-Topic Discussions / I wrote a joystick tester
I wrote this a while ago, but I had reason to use it again recently.

https://github.com/FlyingJester/joystick_test

It's a joystick tester, and it's mostly useful when you want to know what number a certain button on a joystick is, or what the name and number of the joystick itself is. It's also fairly useful for calibrating the joystick if you want to know where deadzones are.

I remember that Windows 2000 had something very much like this, but only for gameport joysticks. I assume it was killed off because the gameport was (sadly) deprecated, but I've never really come across a nice replacement for it. So I wrote my own, while working on a beat-em-up that used SDL2. I figured I'd share it, in case someone else needed it.

It depends on SDL2 and fltk, although the fltk part is optional, in which case it runs on the command line only.
3
Resources / Some Fonts for Sphere
I haven't been all that active in Sphere development these days, but most of my newer projects are still using Sphere-related tech in some way :)

Most consistently I've been using Sphere-format fonts in my other projects. As such, I've got a few fairly good-quality, free-use fonts converted for Sphere-compatible setups, as well as a simple library (well...) for using Sphere fonts in C/C++. I've commited the fonts to the Sphere Group, and the script is up on RMN.

Fonts:
MS Selawik, a sans-serif font that looks pretty nice in bold.
SGI Screen, a classic monospace font.

Both of these fonts were previously proprietary, but have since been released as open by their owners (Microsoft and SGI, respectively).

Sphere Fonts C Source:
http://rpgmaker.net/engines/custom/utilities/102/

I've been using a slightly modified version of this utility in a full-custom game I've been working on. It's setup for use with SDL2, but it's pretty simple to modify it to use any other format (such as here). This is particularly interesting because I've ensured that it works via Emscripten, so you could use it to parse rfn fonts on the web.
4
Off-Topic Discussions / Google's Machine Learning
http://blogs.wsj.com/digits/2015/06/26/artificial-intelligence-machine-gets-testy-with-its-programmers/?mg=blogs-wsj&url=http%253A%252F%252Fblogs.wsj.com%252Fdigits%252F2015%252F06%252F26%252Fartificial-intelligence-machine-gets-testy-with-its-programmers

I don't find this very eerie at all. The machine is still generating its responses from human input. To anthropomorphize it, it's just acting like that to fit in, because everyone else does it. It's similar to if I made a terminal emulator that printed "I don't want to" instead of executing commands.

So I began to think about it, and here are my rambling thoughts about anthropomorphic machine learning.

It makes me think, it would be more meaningful to me to see that kind of response come solely from non-human input. Depending on your view of the universe, that's how human (and in general all biological) behaviour evolved. It makes me think, something like the hardware random-number-generators some of old servers have would be good input. Since they produce output based on radioactive decay, using it as input for things like RNG's is totally fine. It's untainted by human hands, and unpredictable by human means. It could be considered a totally mechanical input, in a sort of romantic way.

It would lead to output we couldn't immediately understand, but generated with similar rules, something in some ways meaningless. Which makes me think...it's kind of like how droids talk in Star Wars. Maybe that's a good representation of where machine-learning with most input only from other machines would go. I did a little experiment a bit like that a long time ago using simple chatterbots, to see what would happen if I fed the input from one into the input from another. Of course, it became a very repetitive and meaningless. But it makes me imagine, in a case sort of like Star Wars, if the machines did 99% of their communication with each other and only 1% with humans, it could lead to small changes that keep a machine language working (especially with a large enough group 'talking' together). Maybe sort of like how human speech has onomatopoeic sounds. Just something taken from totally outside where it used, like a sound of the natural world used in human speech.

But it would be interesting to see where totally machine-to-machine based learning could lead. If you want some kind of self awareness, it's boring for a machine "learns" to act human. It would be interesting for a machine to learn to be a machine in that same manner.
5
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=786909
So I guess Chrome and Chromium installs a binary blob that can listen using the microphone at any time. Even on Linux or FreeBSD. Even when you compile it yourself.

I have said before that Chromium isn't entirely free, that Firefox is the only modern browser that is 100% open and free. Chromium even has some obvious binary blobs for its plugin system and for media decoding. And just because it's open does not mean it can be trusted, any more than you can trust OS X because it's open.

This is not what I was speaking of, but it proves the point. If you are concerned with its connection to Google, Chromium is not a clean alternative to Chrome. It is still water from the same poisoned well.
6
Off-Topic Discussions / WebAssembly
https://blog.mozilla.org/luke/2015/06/17/webassembly/

So, this is what happens when the NaCl and asm.js folks compromise, I suppose.

I don't really do anything that would make me immediately want to use wasm, but I do like the idea because I think it will make asm.js a little less important. I like the idea that there will be a cleaner divide between how JS is used effectively and how asm.js is supposed to be used. JS no longer will need to be a medium for the ASM of the web, it can only be a higher level construct.

Of course, the advances in performance from asm.js are still good to have, and it's good that JS performance has gotten such a huge boost so far. I highly doubt that raw JS performance will stop being important in the near future, even with wasm.
7
Off-Topic Discussions / Monolith First
http://martinfowler.com/bliki/MonolithFirst.html

I had to think about it awhile, but I actually really agree. Modularity, hierarchical systems, and microservices are cool, but most of the best non-monolithic stuff I've done started out monolithic and was later broken up.
8
Off-Topic Discussions / I wrote a lexer generator
At some point early this year, I decided that all code editors were terrible. MSVC is slow, XCode is really weird and a little buggy, Notepad++ and Pe and the Programmers Notepad are not cross platform, and Code::Blocks and Codelite are super buggy.

So I decided to write my own. Which has turned out to also have a few tough bugs in it. But in the process, I wrote a lexer generator. I started using Flex, but holy cow it is ancient. It's just so...dusty. It works in such a strange way, and generates such huge files. Plus, it's really annoying to use, since it's so flexible that doing anything at all is really difficult.

I looked at Sci Lexer, but I then found it to be similarly weird.

Probably Sci and Flex are really normal and I just have a weird idea of what a lexer should look like. But that's probably a good reason to write my own--if I am wrong, I will see concretely why I am wrong and why the right way is right.

But I think I may be right...Lunar generates small and fast lexers that cover what I need for syntax highlighting. I wrote a few other tools with it, such as a tool to check for all the functions that a certain JavaScript file will call, and Lunar's own file parser (not really done yet). It seems quite capable to me.

I based the API on what most nedit editors use for styling (I think). That is, you call:

Code: (c) [Select]

int ParseString(const char * string, unsigned long len, void (*parse_callback)(const char *, unsigned long, int, void *), void * arg);


And when it hits something to lex, it calls:
Code: (c) [Select]

void ParseCallback(const char *str, unsigned long len, int type, void *arg)


Telling you the position, the length, and the type of the token it found.
I really need to add a couple more features before it becomes really useful, mostly allowing spans to be optionally inclusive or exclusive, and allowing a callback for parts that didn't fit any of its rules.
But it's working so far, and it was fun to write!
9
Off-Topic Discussions / ES6 For-Of loop
https://hacks.mozilla.org/2015/04/es6-in-depth-iterators-and-the-for-of-loop/?utm_source=Newsletter&utm_medium=email&utm_campaign=DevProgram

This looks very cool. It's kind of what for-in seems like, but instead of actually iterating properties it only iterates using the data itself.

Seeing this (especially with destructuring), though, it makes me wish that there was a way for an object to expressly rewrite the data operator, sort of how toString() can be used.
10
I've been more interested in CI services since I largely switched away from Linux. My two main platforms, FreeBSD and OS X, use Clang rather than GCC. My other favored platforms are...weird...and so the results of their builds generally are not of interest to anyone but myself.

I used to use Travis-CI, but it is based on ancient Debian (itself ancient to begin with). They have had repeated delays with updating to Debian 6 (Debian 8 has only just come out -_-).
Their tools are simply too, too old for me to use. They include GCC 4.6, which cannot handle C++11, and it does not have SDL2 at all, fltk>=1.3, or a recent enough Python to build TurboSphere. I don't require much of my Python environment, just Python 2.7 (which came out several years ago). I don't want to have to manually pull and build basic requirements for my projects, like SDL2, as a part of my CI build.

I've been trying Semaphore, and I'm pretty impressed so far. It allows integrated build steps from the web interface, so I don't have to add a CI config file to the repository for my project. It is also based on Ubuntu 12, so it has reasonable included tools and available packages.

I'm curious if anyone else has a favored CI service.
11
Off-Topic Discussions / Thoughts on ES6 Classes
Someday, perhaps I will feel a different way. I'm also speaking a bit of hyperbole here to make my point. But this is what I think about ES6 classes.

They are not necessary, and generally a poor fit for JavaScript.

The way to do inheritance in JS, using prototypes has been called a hack, but it's actually inspired by how SmallTalk works. And SmallTalk is one of the older and more pure object-oriented languages. When prototypical inheritance is called a hack, it implies to me that writer is simply not aware of non-class-based object paradigms. Modifying and assigning to a prototype is simply another way to do it.

So why do I think that prototypical objects are a better fit for JavaScript? Because in JavaScript a function and an object are largely interchangeable, and because JavaScript is duck-typed.

I believe the functional aspect of JavaScript better suited to prototypical objects because with prototypical objects there is no need for a class definition. The constructor, a function, is the definition. You can add methods to it by adding to its prototype. This is better suited to functional programming, or a mix of functional and object-oriented programming, because now the object's definition is a function, and an object is (in a way similar to SmallTalk) a function that has a captured and maintained scope.

Duck-typing is quite useful here because it makes arbitrary extension of the prototype more natural. Since there is no formal class definition, you can attach anything to it and not be violating some definition. All that matters, the actual requirements of the 'class', is how it is used. Does it have a 'quack' method? The requirements are the usage.

Perhaps this is just a rationalization to have duck-typing. But it seems to work well here.

Maybe I'm just set in my ways. But I feel that in many ways, ES6 Classes are an extension that is solely to make programmers from class-based languages more comfortable. They don't add much value to JavaScript, except to make it look more like another language.
12
My unnatural obsession with Sun computers has reached a new peak. I have DosBox running usably on 2002-vintage Solaris servers.

https://drive.google.com/file/d/0B-hkR9nzCDDKaWVQN2NOalk1SU5fZ2dMamViZkVrU0JvQWxN/view

The main issue I ran into is just getting these machines started into X11 in the first place. There are three blessed ways to use a Sun Fire server. The main way is using the LOM or ALOM port, which is a serial port that is always broadcasting. The way you would generally log in and use a production machine would be over ethernet--IPv6 on gigabit, even in 2002! The last way, which had a lot of support from Sun and Oracle, but is generally not done, is a full graphical login. Obviously, I went graphical.

The issue here is that almost all the machines I own have been locked down from the LOM/ALOM to drop all SSH connections and not use any graphics cards. Of couse, you also need a special Sun-blessed graphics card to do this, which run ridiculous prices on eBay. I was very fortunate to get two XVR-100's (Radeon 7000s) and one XVR-250 (Radeon 9000) with my lot of servers.

To enable graphics, I had to somehow get around the ALOM password. I decided on using a Sun Fire v240, since most of the machines I own are this model. These machines need a key to start them. I'd seen this kind of thing before on old Dell PowerEdges, but one interesting aspect of the Fire series is that you can also use the key to select a diagnostics mode on startup, which ultimately tries to boot from disk regardless of the options you select in OpenBoot (which was what everything except x86 uses instead of BIOS, until EFI came out).

QUite luckily, I discovered that if I started a Sun Fire v240 in diagnostics mode, I could then turn it back to normal mode while it was doing diagnostics, and instead of a normal bootup, I was dropped into the ALOM prompt as the default admin account without entering the ALOM password! I've tried this on several other FIre-series servers, and it seems they all do this. Do'h!
From here, I was able to first enable video, and then change it to 60 hertz (for some reason, all Sun cards want 75 hertz. Was this standard for servers in 2002?)

Then, it was a relatively simple matter to download DosBox for Solaris 10 UltraSparc and grab some of my old games (Daggerfall pictured, SimCity 2000 also tested quite thoroughly). Yes, there is a version of DosBox setup just for this kind of computer...I guess some sysadmins got really bored one day.

My general impression is that this machine, which has 8 GB of ram (expandable to 32 GB), a pair of ZPooled 10k RPM SCSI Ultra160 drives, and a pair of UltraSparc III CPUs (true dual CPU, not dual core) is actually really powerful. I'm only using actual results, but it hosts Minecraft with similar latency to my brand new MacBook Pro. A certain benchmark I found, which some Solaris folks told me proved I was a fool, said this machine shouldn't be much more powerful than an rPi. Regardless of the why, it can run DosBox at full speed, and my rPi struggles to get even a single frame per second in.

Definitely the best ten dollar computer I ever bought!
13
Off-Topic Discussions / Netscape Documentary
https://air.mozilla.org/code-rush/

This is really cool to me. A documentary on Netscape preparing for the Mozilla open source release. I'll just leave it here.
14
So, I've been using the Mercury programming language for a little while now. I've kind of wanted to learn it for many years, but it's extremely different from any other language that I properly know, so until now I haven't really been able to even begin learning it.

I thought I would share what I've learned about it, because I am really happy that I am finally making progress learning it, and because I think it is a really nice language.

Mercury is a functional language, influenced by Haskell, but it's also heavily influenced by the logic language Prolog. All I really know about Haskell is that it is purely functional, declarative, and has a powerful type system. I don't really know much of anything about Prolog. That, and people say "Haskell is unrealistic about some things because it's a research language", and "Prolog is slow". I do know that Mercury has a very similar syntax to Prolog and a very similar type system to Haskell.

What you know about Prolog and Haskell is kind of important when learning Mercury. I found out very recently that almost everyone using it came over from Haskell or Prolog. Which explains why I had such a hard time even beginning to understand it--all the documentation assumes you know either Prolog or Haskell.

So, without knowing much about its roots, what do I find interesting about Mercury?

Mainly, how it allows you to express the state of a program. I think this is a good example of the interplay of logic and functional programming:

Code: [Select]

% from a small directory searching routine

% This is a disjunction. The closest thing you could relate it to in imperative programming is a set of logical-or statements, or kind of a switch statement.
% PathType has been assigned, OutPath has not been assigned yet. Both are a 'maybe' type.
(
    PathType = yes(directory),
    OutPath = yes(InPath)
;
    % After each semicolon is another possible state.
    PathType = yes(file),
    OutPath = yes(InPath)
;
    PathType = no,
    OutPath = no
)


In that case, PathType is a variable that has a state already. If it is equal to `yes(directory)' or `yes(path)', then the OutPath variable (which had not been assigned a value yet) is now set. Otherwise, this predicate (kind of the same thing as a function) fails.

With SLD resolution (which I'm told is inherited from Prolog), the idea of left-hand and right-hand expressions doesn't exist. Either a state is possible or its not. So what stops PathType from being reassigned? In Functional languages, a variable can only be assigned once. That's the combination of logical and functional programming: You describe the state, and if the state is possible based what values have been assigned, it becomes so. If two states are possible, but mutually exclusive, the compiler will know and your program won't compile.

To this end, there are many nice ways of expressing logical relations, such as the disjunction. While in that example it assigns to OutPath, the entire disjunction (everything in the parentheses) is itself a boolean expression. If any of the states it lists are possible, it is true. It's an expressive logical-or statement! There is a similar expression, a conjunction, which is the same as a logical-and statement. In fact, it's written using commas instead of semicolons. Which means that everything is either a huge logical-and statement, logical-or statement, or combination of the two. Your entire program can be said to be true or false, deterministic or non-deterministic. This means that it's simple to statically analyze the program and determine if a predicate has one solution, many solutions, or no solutions. Similarly, it's simple to see what predicates may fail.

Of course, there are a LOT of things I still need to learn. The determinism system in Mercury is much deeper than I understand right now, and I don't fully understand functional purity. But now that I'm actually making progress, and I understand some of the foundations of logic and functional programming, I'm rather enjoying learning Mercury.
15
For a long time, it was basically impossible to work with binary data natively in JS. Sphere solved this problem with a custom object, the ByteArray.

But time's change, and rooms are rearranged. Now we have TypedArrays, which are explicitly meant for the same task.

I've written a script that implements the ByteArray object using TypedArrays. I intend this to be the basis of the implementation of ByteArrays in TurboSphere, especially because TurboSphere will use TypedArrays in its API instead of ByteArrays.

https://gist.github.com/FlyingJester/03c7a0ae4a5d782d114b