Pirix: Workstation Pi Desktop

Another random concept for a pi-based concept. This one is a lot less ambitious than any possible handheld. The idea is to make a case for the Pi to hold a floppy drive, fan and mSata drive, and then have it look like a work station from the nineties, and then load it up with a customized version of XFCE4.

So why a floppy? Generally because it’s easier to use than a cd (in terms of read – write), and I’m interested in how much data can be packed onto a floppy disk. With source files, it would be interesting to manage them with a floppy (and of course with Git). For the mSata, I’m finding that using an SSD is stupidly faster than using an SD card. I can’t quantify exactly how much better, but everything feels so much snappier to the point where it doesn’t make sense to go back. And lastly a fan, the Raspberry Pi 3B+ get’s stupidly hot. And small fans are noisy, so I want to mount a decent size fan into the case to get air passing over a heat sink.

Approach is going to be start cheap and work my way up. I think I could start with something simple like a clip board, drill holes into it and get stand offs for the parts, and tie cables down, to get a working proof of concept to start. And then from there start figuring out parts I can implement better. I may be able to order custom cut acrylics and work towards a better proof of concept from there.

Edit:

Dropping a picture of the Think Centre desktop to act as a reference.

Lineage OS Wishlist

I hate a love/hate relationship with cell phones. Mostly I dislike them and would probably be a lot better off ordering a Librem 5 and not looking back. But I like Lineage OS, and I especially like the fact that you can buy old Android phones, and then flash them to have an extremely light version of Lineage OS running. And then only install FOSS software on top of that. So there are a lot of phones I would like to get my hands on to see how the experience works out.

Google

  • Nexus 4
  • Nexus 5
  • Nexus 5X
  • Google Pixel

On the Google side of things we have the Nexus 4, Nexus 5, Nexus 5X and Google Pixel. I’ve been using the Nexus 5 for the last few years, and aside from the terrible camera, and terrible reliability, it’s actually a pretty good phone at the core. Though I had a phone where the microphone didn’t work, one died from an official update, one of them the battery would only last a few hours. So in general two out of three of the Nexus 5’s that I’ve bought in total have failed on me in some way. So it’s hard to recommend them to someone. So I’m skeptical about the Nexus 4, which is only on here because there are no small form factor cell phones any more, and they are dirt cheap, so it would be interesting to get one for testing and to see how it works. And while I haven’t had much luck with the Nexus 5, the Nexus 5x comes with a better camera and usb, so it would be interesting to get my hands on the actual device. For the Pixel, it just arrived a few days ago from ali express, and I haven’t spent much time with it yet.

Samsung

  • Galaxy S3
  • Galaxy S4 Mini
  • Galaxy S6
  • Galaxy S9

For the Samsung side, the S3 probably isn’t needed, but it’s actually been on my want list for a long time. So it would still be interesting to test if I can get my hands on one. The Galaxy S4 mini, because it’s a form factor that’s not often used. And in my case I mostly use my phone for music, and the occasional picture or text message. The Galaxy S6 is fairly recent, but is getting pretty cheap now with how cell phones develop. And it comes with a pretty decent camera and wireless charging. And lastly the Galaxy S9, which doens’t look like it should be on this list, as I would normally just want a S7. But the S7 still comes with a micro usb, which is totally stupid. And the S8 doesn’t support Linux. So most recent Samsung phone to support Lineage OS and have a usb-c charging port is the S9, which is stupidly expensive, but maybe someday.

Summary

Not sure if it’s actually worth it, since I could probably just order another Pixel if I ever needed a phone, since it pretty much out ranks the other phones on the list (outside of the S9), while not costing very much. So it depends on how much I actually want to invest in hardware that’s just going to sit in a drawer. But quick note, the Nexus 4 and Nexus 5x, I can probably pick up on amazon, while the samsung phones will probably require me to order them from ali-express.

Edit

Prices on the Nexus 4 aren’t as dirt cheap as they were. So with the Galaxy S4 mini probably being a better built phone with more reliable specs at a similar price, it makes owning this phone a lot less of a must have. But it would still be interesting to get the Nexus 4, assuming there was a decent deal on it.

Planning out Dash Model Format Version 2

So back of the napkin style, file layout planning. At the top of the file will be the magic number, version number, offset to the table of contents, and length of file. Though for the length, it’s the length of the file from the start of the table of contents, until the end of the file, not including the magic number and copyright, meta information. The meta information is located in-between the offset declared after the magic number. In general, this is not needed, so it could be located right after the first line in the file, but at the very least the file definition and export tool should be listed in this area. And in the case of copyright, the creator should declare what rights they intend for their creation in the file, to avoid confusion.

After that comes the table of contents with the number, offset and length. So the first offset from the images should come right after the table of contents (if exists). Otherwise the offset from the first material will come right after the table of contents.

Which means I need to start planning out the exporter for a Threejs plugin. So The first step will be to create a constructor for the exporter. The next step will be to create a parse function that accepts parameters for the author and copyright. The next step will be to break down the images, textures and materials into structs and then write the images, textures and structs. Since I have the base from the first version of the Dash Model Exporter, so I can take notes from my original exporter. And the last thing is in the case of Threejs, I should probably use Buffer Geometry and not normal geometry, because it’s easy to convert normal geometry to buffer geometry, and then break down the attributes into the specific lists.

Methods of Packing Animation Data

To make things simple, I think I can use a fixed struct for the animation data. To put it simply:

typedef struct DashKeyFrame {
int frame;
int bone_id;
int parent_bone_id;
char use_position;
char use_rotation;
char use_scale;
char nop;
vec3 position;
vec3 rotation;
vec3 scale;
}

I think the above struct will allow me to use a fixed struct for each keyframe. Since for every frame, and every bone we need to have a transformation matrix to tell the mesh how to deform. But with the use of interpolation it means there are a lot of values that get automatically get filled in. And we can’t make the complete assumptions about just filling in all of the keyframes, otherwise the data that gets saved into the file and read from the file becomes drastically different. Also in a lot of cases the use of nested arrays is used to manage this information, and even though it’s redundant, just including the frame number, bone id and bone parent id in each keyframe removes the need to use any kind of nested structure in the data.

As for the character boolean values, we have one value that tells the importer to use position or not, rotation or not and scale or not. The effect of this is that there can be alot of data with default zero values are included in the data, but in this case simplicity and a fixed structure take priority, so I won’t lose much sleep if a few extra bytes is included here or there. The one weird part about all of this is the frames per second value, which I figured I might as well include as the fourth byte, otherwise it’s just a no operation byte anyways. So while I’m okay with wasting bytes for the sake of having a fixed struct, we also might as well use bytes that aren’t really being used for anything. I think this makes a change to the animation entry.

typedef struct DashAnimationEntry {
char animation_name[0x20];
unsigned int animation_id;
unsigned int offset;
unsigned int offset;
unsigned int number_of_keyframes;
unsigned int frames_per_second;
unsigned int number_of_frames;
unsigned int nop[2];
}

So I end up adding two nop values to the end of the animation entry, and then one nop into the keyframe values. But I guess that’s acceptable.

Alternative Media

After using my last post to think through my blunder of buying the geekwork case, it gets even worse, but I’ll get to that in a second. For my previous post I came to the conclusion that a normal Pi 3B+ hosting an access point is the correct way to go. And after creating the pi with the access point, I can see that if I need any extra space for Next Cloud or otherwise, I can either buy usb flash memory or a usb mSata drive. What makes all of this worse is that in the time I was waiting for my hard drive and geekworm case to be shipped, the prices of storage really fell out the bottom. In this short amount of time, several prices have been sliced to half making the trade offs of price versus space I was running into before a lot more one sided in the favor of flash storage. That being said with a 128GB usb stick now coming in at around thirty dollars, it makes it a lot easier to either pick up a stick, or maybe even hold out until there’s an even better deal down the line.

Which kind of leaves what to do with the alluminum case and hard disk I bought. After after thinking about it, I think the best use of the case and hard drive is probably to host a network storage drive up stream from my pi access point. This means that I should be able to get wired transfer speeds over the local network and then a pretty dedicated connection for the few clients I have connected to the access point. For a host I think I’ll use my tinker board, which kind of kills two birds with one stone, as the Tinkerboard has two gigabytes of memory and gigabit Ethernet, but it’s been sitting in my drawer for the last year, because it’s non-standard. So I can feel better about using all of the non-standard “junk” i have laying around to use the barrel jack to power the tinkerboard, to host the two terabyte drive on my network or act as a backup.

Piboy Pocket

Quick outline for the “Piboy Pocket”. Originally the idea was to use either a Raspberry Pi zero, or the Raspberry Pi computer module with an e-ink screen to replicate a Gameboy Pocket. Though after finding out how slow the refresh rate on an e-ink device screen is, that doesn’t seem like a viable option, at least for now. And if anything I think the Arduboy fits this niche pretty nicely already. And rather than a Pi the Arduino makes more sense for this task. Not to mention that $50 for a completed product than trying to roll my own (in this case). That being said it looks like the arduboy is out of stock, so it might be worth ordering one if I ever come across one.

Dash Model Format Version 2

I think I have the header defined for the next version of the dash model format

Offset 0x00 0x04 0x08 0x0c
0x0000 DASH 2 offset length
0x0010 IMG num offset length
0x0020 TEX num offset length
0x0030 MAT num offset length
0x0040 VERT num offset length
0x0050 FACE num offset length
0x0060 BONE num offset length
0x0070 ANIM num offset length

IMG

Images and animations will be in archive. For image, i think the archive struct will be:

typedef struct DashImage {
	char image_name[0x20];
	unsigned int image_id;
	unsigned int offset;
	unsigned int length;
	char image_extension[0x04];
}

TEX

For textures, since we don’t need much I think we can use the following:

typedef struct DashTexture {
	char texture_name[0x20];
	unsigned int texture_id;
	unsigned int image;
	unsigned int wrapS;
	unsigned int wrapT;
	unsigned int flipY;
	float rotation;
	vec2 center;
}

Generally which image to use, how to wrap S and T, whether to flip Y or not, the rotation (in radians) and the center. Probably won’t use all of these, but it should allow for these values to be utilized if needed, even if I never use them.

MAT

For materials, the main issue I think is how to manage blending.

typedef DashMaterial {
	char material_name[0x20];
	unsigned int material_id;
	int texture;
	float alpha_test;
	float opacity;
	char vertex_colors;
	char blending;
	char blend_src;
	char blend_dst;
	char side;
	char transparent;
	char visible;
	char skinning;
	DashColor diffuse;
	DashColor ambient;
	DashColor specular;
}

For materials, generally the aim is to go for something between lambert and phong. We only need one texture coordinate, since bump, environment and lighting maps are beyond the scope of what the goals of this file format are. Values that are not defined can be ignored, like blending should be 0 is no blending is defined, ambient and specular can have 0 for the fourth bit to indicate not to use them. And as for vertex colors, if the face defines them, then i’ll set the value for the material if needed in the importer, but I don’t think the value is needed in the struct, though I might add it just the be safe.

VERT

Vertices should be pretty easy.

typedef DashVertex {
	vec3 position;
	unsigned short indices[4];
	vec4 weight;
}

A vertex is defined as a position combined with a weight and index. If there is no weight (or index), then just fill in zero.

FACE

The face we already defined in a previous post. I don’t really see any need to change anything. The only part that annoys me is the use of nop to fill in space between four byte boundaries. Though I could just make the indices unsigned ints, but that would be kind of stupid when passing to the graphics buffer. So I might take another look and move some crap around.

typedef DashFace {
	char materialIndex;
	char useVertexColors;
	char useVertexNormals;
	char useTexCoords;
	unsigned short indices[3];
	unsigned short nop;
	vec4 vertex_colors[3];
	vec3 vertex_normals[3];
	vec2 tex_coords[3];
}

BONE

For the bones I kind of want to throw everything in (including the kitchen sink). Calculating values for bones can be annoying, so if the program provides these values it would probably be best to use them, or at the very least be required to know how to calculate them, so they can be verified.

typedef DashBone {
	char bone_name[0x20];
	int parent_bone_id;
	int bone_id;
	vec3 position;
	vec3 rotation;
	vec3 scale;
	mat4 matrix;
	mat4 inverse_bind_matrix;
}

So pretty much include everything. Local position, local rotation, local scale, local matrix, and inverse bind matrix. If an importer works better with one more than the others it can just be used, otherwise, these values can be calculated as needed.

ANIM

typedef DashAnimationEntry {
	char animation_name[0x20];
	unsigned int animation_id;
	unsigned int offset;
	unsigned int length;
	unsigned int frames_per_second;
}

Animation entry is just a carbon copy of image entry, since it’s basically an internal archive. For the actual animation data, there are three options, fcurves, so a value for a given axis for a given time, or a collection of key frames for specific frames, or lastly a key frame for every bone, for every frame in the animation. I’m really tempted to go with the last one because it makes reading and writing stupidly easy, and these values can be optimized by the importer if needed.

DashGL Format, Support and Faces

In general I’m pretty happy with the texture and material approach I came up with in one of my earlier posts. By standardizing the structs with respect to textures and materials and keeping the options limited, we can simply our header file. Though this leaves us with a few issues. If it’s possible to simply most of our struct type entries, is there a way to standardize images, faces and animations so that these only have one entry? And then in terms of entries, is it possible force a fixed header, or will the header depend on the type of the content?

In general the goal is to create a binary file format that only supports a fixed number of attributes and is geared towards models that were around in the mid-1990’s. So basically meshes, rigged meshes, and rigged meshes with animation. In terms of faces, we’re looking to normals, vertex colors, and texture cords and whether to use them or not. Which means we could potentially use a face struct similar to the following:

typedef struct Face {
char materialIndex;
char useVertexColors;
char useVertexNormals;
char useTexCoords;
unsigned short a, b, c, nop;
vec4 a, b, c;
vec3 a, b, c;
vec2 a, b, c
}

So that basically for each face we have a material index, whether the face uses vertex colors, vertex normals, and/texture coordinates. For materials I imagine it would be difficult to use more than 256 materials in a single file, but if that ever becomes an issue we can just increment the file type number. For the boolean values it would probably be simple to just use bit flags, but I think that would be cramming things down too much. Using structs means that we can include the definition of what each value is doing directly into the source code, where as with flags it would have to be describe somewhere else.

Following that we would have the indices for the a, b, and c values for the face. For the indices I think that we would define a vertex as a x,y,z position combined with a weight. So I might force the vertex list to be declared with the weights required, and then just set to all zero if not used. It seems kind of wasteful for files that might not use it, but in comparison I think the saving from using binary over text are going to be sufficient. And it also has the benefit that there are no major structural changes in the file for if a mesh has weights or not (i’m looking at you .dae). Which means we could get the file header down to something that looks like:

IMG
TEX
MAT
VERT
FACE
BONE
ANIM

And then that would make it easier to just simply require all of the things. For IMG and animation, I think we could declare the number in the header, and then just have the number of bytes before each image is declared and then just read the number of images from there. And then do something similar with animations. What would probably be more “computer-sciency” and cleaner would be to have a look up table at the top of the IMG and ANIM sections to be able to have a global offset to just to to read the information. So the section would basically have it’s own mini-header. That way someone could read the header, and then read the offset to a given image rather than having to loop through all of them. It would also make the file a little more forgiving to edit (not that I can see too many people editing by hand), but it has the added benefit of having more nerd points.

But packing all of the attributes in this way means that I could have a very simple header (type, offset, count) with a fixed number of entries. And then a simple list to determine what kind of mesh the file is. If there are bones, then it’s rigged, no bones, then it’s a mesh. Bones and Animation, then it’s rigged with animation, though the main detail is to look at the bones, to determine yes or no.

GeekWork Case

I think this experiment might go into the “failed” bin. At home I’ve been increasingly using Raspberry Pi’s to replace any computing needs I might need on a network. Why raspberry Pi’s? Because their ubiquitous, it’s easy to find documentation for them, they only require a micro-usb to power them, generally that amount of computing power is more than enough for a web server, and most importantly it’s a good learning experience to create your own devices and match them together rather than buying something complete.

Specifically my goal for this case is to have an access point for my house. This goes hand in hand with my Android to Lineage experiments. But basically I want to have LineageOS on my cell phone. Then I want to host NextCloud at home. And then to use NextCloud on my cellphone, my NextCloud instance needs a valid https certificate. Which means that my plan was to use my super-cheap cloud server to verify my certificate, have a Raspberry Pi act as an access point, and then use nGinx to forward the traffic back to my NextCloud instance.

Though as I’m writing this I’m realizing a pretty big mistake that I was making. My intention was to make a single device that would perform all of these functions. But In reality I think it would make a lot more sense to simply have a barebones access-point with minimal functionality on it, (just the access point and a DNS server), and then start adding Raspberry Pi’s into the network with fixed ip’s and DNS entries and just have them all forwarded from the central access-point-pi.

Planning out the next Dash Model Format

In the last post I examined gltf and I think it has too many issues to get involved with. That being said, I definitely won’t complain if there is some ground swell of support and devs can magically make the file format viable, but until then I’m not holding my breath. I think it would be a better use of my time to address the issues with the Dash Model Format and amend them so that I can start working on a Noesis plugin or something.

One thing that became clear after looking back over the gltf definition is that it does make sense to split the image and the texture, which is something I was having trouble with. As the attributes for textures can be a set struct, but the image is a variable length file. Granted I can have the image merged into the texture, but it makes the file format really ugly. So what I’m thinking of now, is having the images listed individually, with the count being the number of bytes. And then textures and materials can be structs with the count representing the number of structs in the array.

Type Offset Count

IMG 0x100 0x123
IMG 0x130 0x395
TEX 0x400 0x2
MAT 0x420 0x2

Which I think makes the image, texture and material management really clean looking. The only other consideration is the option to add names into the file. Something I’m tempted to leave out completely. But if I do put it in, I can allocate 0x20 bytes to a name string and the beginning of the texture and material structs respectively to define a name. Since Images are already using the byte length for the count, I don’t think it’s a good idea to add in names, so if it’s needed it can be included in the texture if needed.