Thursday 2 March 2017

Free 3D Point Cloud Viewer utility

3D Point Cloud Viewer

If you have a passing interest in 2D/3D digitizing, reviewing point clouds, creating your own homebrew scanners or any other data capture projects you will understand the need for a lightweight point cloud viewer. You will also understand that you don't want to purchase expensive software like Geomagic, or LeiosMesh just to review captured points and you certainly don't need the advanced capabilities of surface meshing or advanced measurement and editing tools at this early stage either. 

If like me you have lots of small files with captured point cloud test data that you just want to see quickly, then this is where this utility comes in handy.

Features
  • View full colour point clouds (single colour point clouds if no RGB available).
  • OpenGL
  • Rotate, pan and zoom
  • Interactive point size ' fake solidify'
  • Data scan dimensions and statistics
  • Visual axis On/Off
  • Lighted/darken brightness (slow on large sets)
  • Hardware vertex shading - Select 'green solid type shading' for single colour point clouds

Download the free utility here:

Executable, example scan, file format descriptions and Freebasic source code available from the link.



Friday 9 September 2016

Circumventing timed nag screens using AutoIT


Nag Window Problem


I frequently use a small utility for my 3D scanning projects called Points2Polys. It's an older free utility from Paraform that's really useful for viewing and skinning point clouds. Unfortunately being free software Paraform decided to place two annoying nag windows in the program which appear ever time the utility is used. The first nag window displays a branded image for 3 seconds and a second nag window is displayed for a further 10 seconds. The second window can only be removed by clicking on the newly enabled close button (close button is disabled during the 10 seconds wait).

Since these nags slow down productivity I had wondered about removing or altering the timing values in the executable program code and removing the nag screens using hacking techniques. I did eventually try various cracking methods but ultimately I wasn't skilled enough to find the important code blocks and remove the problem.


AutoIT


After further thought I realised that I could alter the window elements using AutoIT. I previously used AutoIT to write CrossBro. AutoIt is a very powerful scripting language used to automate everything in the Windows environment. Using its built in functions I could close windows, send simulated key presses and manipulate associated Windows GUI elements automatically.

Further research and a few prototypes later proved that Points2Polys was using standard Windows GUI API elements that could easily be manipulated in the way I wanted. I still wasn't able to change the timer values but did noticed that once I had enabled the Close button the nag window could be closed immediately. 

Using AutoIT I manged to script a series of simple actions to complete the task.

1) The script runs Points2Polys.exe
2) It closes the front nag window by sending a simulated right mouse button click
3) It selects the second nag window using its window title name
4) The Close button is enabled with one simple command
5) A virtual keypress is sent to the Close button which closes the nag window fully

I also added a final command to resize the application window to fit my screen size.


Solution


This script finally enabled me to use Points2Polys the way I want. I still see the nag windows briefly after startup but they both disappear shortly afterwards leaving the interface clutter free and ready for use.

Download: Points2Polys

AutoIT Script


;AutoIt script
;https://www.autoitscript.com/site/autoit/

;Points2Polys loader without nag screens by Colin Ord, 7th Sept 2016

;Script purpose
;To automatically circumvent the two timer driven nag screens

;Solution
;- script opens points2polys.exe
;- script closes the initial nag screen by sending a simulated mouse press to the application
;- script then 'enables' the disabled close button
;- script sends a Left mouse click to the newly enabled close button control closing the second nag screen
;- script also resizes the window dimensions to fit the screen

#include <MsgBoxConstants.au3>

;#include <GUIConstantsEx.au3>
;#include <StaticConstants.au3>

loader()
Exit

Func loader()
    ;run Points2Polys
    Run("D:\Program Files (x86)\Paraform\Points2Polys\Points2Polys.exe")

    ; Wait 10 seconds for the Points2Polys window to appear
    Local $hWnd = WinWait("Paraform Points2Polys", "")

   ;close the 1st nag window - automated mouse click
   MouseClick("Right")
   Local $hWnd = WinWait("Paraform Points2Polys", "") ;

   ;enable the disabled (greyed) out close button
   ControlEnable($hWnd, "", "[CLASS:Button;INSTANCE:1]")
   ;close 2nd nag window - click the enabled close button
   ControlClick("Paraform Points2Polys", "", "[CLASS:Button;INSTANCE:1]")
   ;resize window to fit screen
   WinMove("Untitled - Points2Polys", "", 480,140,960,700)

EndFunc   ;==>Example


Thursday 21 January 2016

DIY 3D Digitizing Arm



*This text is a work in progress and will be updated regularly*

3D Digitizing Arm Project

For many years I dreamt of creating a 3D digitizing arm similar to the great Microscribe3D or FaroArm products. I've dabbled in various data gathering projects before e.g. building a 3D laser scanner, 2D computer vision for extracting data measurements and 2D motion capture for animation purposes but to this date the unique mechanism of these digitizers has always intruiged me.

As usual my inquisitive nature got the better of me and I was pretty sure I had the skills to build my own 3D arm based digitizer. I gathered as much technical detail and knowledge as I could find relating to how this device functioned and set about the project with eager interest. This article follows and details the project to completion with photos of the prototype arm, the serial connection utility and the Blitz3D virtual interface.



Approach

Without access to a real Microscribe I had to research it's characteristics by watching product videos, reading patents documents, manuals and product reviews. I gained invaluable knowledge into its mechanical inner workings, its precision digital encoders, and how it applied complex trigonometry in hardware to work out the location and orientation of its digitizing tip. These findings were crucial to help formulate a solid idea in my mind of how to simplify the whole project, keep costs to a minimum, yet still create a fun 3D arm digitizer that was reasonably accurate and robust.

Project Kit Requirements

  • Arduino Uno
  • Four potentiometers
  • Micro switch 
  • Wooden doweling 
  • Jump wires
  • Screws
  • Tie wraps
  • Blitz3D
  • VB6

Building The Prototype


Prototyping the initial idea using potentiometers and cardboard lengths.

Testing realtime data capture using my custom Arduino serial driver and Blitz3D.


Testing complete! Building a sturdier arm using wooden dowel.

Arm complete and used to digitize a small statue.

  Digitizing complete. Point cloud viewed on Points2Polys.

Digitizing a 2D illustration

Digitizing an object (slipper)

Real time point cloud visualisation in Blitz3D

3D object point cloud

Thursday 5 February 2015

Extreme programming - Hand coded executables using only MSDOS ECHO!

Hand coded binary executable programs!

This article will show you how to hand code 'executable' files (*.COM files) at the DOS prompt WITHOUT ANY OTHER 3rd party programming environments, debug tools or hex utilities. All that is required is a PC with MSDOS prompt, the ECHO command and a standard 104 keyboard (with keypad). With this technique you could create very small programs e.g Viruses, Copy/Dir utilities just by typing in the correct opcodes and values in a programatic way!

An understanding/appreciation of x86 assembly language is required since the input is directly related to x86 programming!

These examples were tested in DOS 6.22,  DosBox (DOS 5.00), Vista and Win7 command boxes.

About

A few years ago I found out by accident that if Num Lock was activated and a number between 0 and 257 was typed on the keypad whilst holding the Left Alt key, I could view the ascii character associated with that number at the MSDOS prompt. This trick is well know for accessing special ASCII characters such as the © copyright character which isn't available directly on the keyboard, not so well know is it's ability to create machine instructions and assembly style programming!

Printing ASCII characters to the screen using ALT

*NUMLOCK must be activated, use LALT,  and type all numbers on the keypad

To understand what I mean try the following at the MSDOS prompt while holding the Left Alt (LALT) key down, release the LALT when finished!

The following LALT number shows the single character 'H' at the DOS prompt. 
c:\>[LALT-72]
Produces: H

The following LALT numbers show the word 'Hello' at the DOS prompt.
c:\>[LALT-72][LALT-101][LALT-108][LALT-108][LALT-111]
Produces: Hello

Certain ASCII characters for example CR/LF(LALT-13) or BELL (LALT-7) will cause an ASCII action to happen e.g. newline or produce a beep sound to the speaker, instead of showing its character equivalent. It is this capability to access these special characters (all 256 ASCII characters) that intrigued me to the possibility of being able to produce binary files by hand!

ASCII as binary

Further tests showed that when I redirect a list of LALT ASCII codes through ECHO as output files they would be written as binary (hex) instead. 

This example creates a binary data file named c:\hello.com containing "Hello" text.
c:\>ECHO [LALT-72][LALT-101][LALT-108][LALT-108][LALT-111] > hello.com

What is happening is that when typing the number (using LALT) on the keypad the ASCII character values are being converted to Hexadecimal (HEX) notation. This is exactly what we need because Hex code is the language used to talk directly to the PC! 

COM files, x86 & opcodes

When I tried running the outputted hello.com file above, DOS crashes with opcode errors which is understandable since the hello.com file created above only contained simple HEX text values. The 'Hello.com'  file above didn't contain any instruction mechanisms or MSDOS functions to interact with the user or system. Unless we add these to the file in a meaningful way we won't be able to do anything useful like printing strings to the screen, displaying graphics or writing / opening files using disk functions.

To produce a binary file that does something useful and executable we are going need a little more understanding about x86 assembler programming, registers and opcodes. Unfortunately this involves a lot or research of the assembly language itself, CPU registers and operations codes. These areas are way too vast to fully grasp in this text but with a lot of perseverance, exploring references at the footer of the page and playing with the examples should give you a good starting point to this exciting and unique way of programming!

Your first fully functional hand coded executable program

Type the following key commands at the DOS prompt remembering to hold Left ALT.

c:\>Echo LALT-178 LALT-36 LALT-180 LALT-2 LALT-205 LALT-33 LALT-205 LALT-32 > $.com

Your prompt should look something similar below when finished. Press enter to build!
c:\>Echo ▓$┤☻═!═  > $.com

Run the file '$.com' and you will see a single dollar ($) character displayed on the screen.
c:\>$.com
$
c:\> 

Congratulations! You just created your first hand coded executable file..

$.com - x86 assembly language equivalent
 

The program you typed above is equivalent to writing thefollowing program into MSDOS debug.

-n $.com
-a
mov dl,24 ; place $ character into register dl
mov ah,2 ; sets the dos interrupt function to Display Output the character in register dl
int 21 ; execute the MSDOS function in register ah
int 20 ; MSDOS interrupt to terminate program and return to prompt,
-rcx 8 ; file length in bytes - number of operations 
-w
-q

This program is identical and when run also displays a single '$' character on the screen!

$.com breakdown

We use the MSDOS interrupt function INT21 to display a character onscreen. Its associated sub function number is 2 which is used to 'Displays Output' to the screen 

The INT21 interrupt is a MSDOS function executor. When its called any value in the register ah will be used as INT21 sub function number. When the two are used together in this way a specific MSDOS action will be executed - in this case the Display Output function.  This function also expects a value, a single character, to be present in register dl prior to executing. This character will be a single ASCII character (e.g. ASCII 36  = '$') - encoded into HEX (24 = '$'). See ASCII sheet in the reference section for all the code conversions.

Required programming steps

1) The register dl must first contain a valid single ASCII character
2) The number 2 is placed into the ah register, which is a MSDOS INT 21 sub function to display a single character to the screen.
3) Int 21 executes the sub function 2, which reads the ASCII value saved in register dl. This ASCII character is displayed onscreen as part of this function.
4) Int 20 terminates the program (doesn't require any extra sub finctions) after the character is shown and returns input to the DOS prompt!

80x86 Instructions

Intel 80x86 Assembler Instruction Set Opcodes are machine language instructions that specify operations to be performed. There are 256 (100 in HEX) instructions in the 80x86 set and each opcode uses one of these numbers. Several common opcodes are shown below:

Data movement
mov, lea, les, push, etc.

Arithmetic
add, sub, dec, cmp,  etc.

Program flow
jmp, call, ret, etc.

A comprehensive MSDOS opcodes table can be found in the references section below.

Opcodes - HEX vs Decimal

The opcode table link is a good source for finding the correct hexadecimal opcode number for each instruction.

The '$.com' program you typed above lists the mov dl, opcode. This instruction can be cross referenced in the opcode table as B2. B2 is the binary coded mov dl instruction in hexadecimal format.

We need to convert this HEX number to decimal to use these instructions in ECHO. This will enable us to hand code the opcode at the dos prompt in native machine language.


Converting hexadecimal numbers to decimal is quite easy. Many sites around the internet give access to conversion tools or you can simply using the Windows Calculator.

A good online converter
http://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html

Detailed example

STEP 1 - plan your program if you don't already know assembly opcode values!
This program prints 'hello' to the screen and is written in MSDOS Debug

-a ;assemble code
0100  jmp 108 ;jump past string location
0102  db "hello$" ;string storage
0108  mov dx,102 ;where in segment the string is located
010B  mov ah,09 ;MSDOS output string function
010D  int 21 ;execute MSDOS output string above
010F  int 20 ;Terminate program

-n hello.com ;create file
-rcx:
20 ;rough estimate of program length
-w ;write binary

STEP 2 below shows all the associated opcodes values in HEX. I used the opcode table in the reference section to find these.

EB 06 ;jmp to memory address
68 ;h
65 ;e
6c ;l
6c ;l
6f ;o
24 ;$ - string termination

BA 02 01 ;mov dx, 102
B4 09 ;mov ah, 09
CD 21 ;int 21
CD 20 ;int 20


STEP 3 - convert all these HEX values to decimal ready for inputting into ECHO or to the CON device (see NULL next section)
*Don't include the comments when inputting!

235 ;jmp opcode
6
104 ;h
101 ;e
108 ;l
108 ;l
111 ;o
36 ;$
186 ;mov dx,

2
1
180 ;mov ah,
9
205 ;int
33
205 ;int
32


Your hand coded input with NUM LOCK activated and LALT will look like:
c:\>echo Ù♠hello$║☻☺┤○═!═  > hello.com
c:\>

When hello.com is executed the output will be:
c:\>hello.com
hello
c:\>

The NULL problem!

As you delve further into learning this technique one glaring problem will eventually arise, how to input NULL characters using ECHO. No matter how hard I tried I couldn't get ECHO to produce the Null code using values from 0-255. After much research I eventually found two other key combinations that create NULLs. A CTRL-@  and LALT- 256 both create NULLS!

If for some reason you can't recreate these key combinations e.g. laptop keypad issues you can circumvent this problem by sending the input to CON instead of ECHO.

c:\> copy CON test.com
CTRL @ ;NULL
LALT 256 ;NULL
LALT 67 ;C
LALT 111 ;o
CTRL Z ;save file and exit copy commands

OUTPUT
The small program above will create a non executable binary file with 2 NULLs and then letters 'Co'.
 
Conclusion

I confess that I'm not an assembler programmer or guru by any means. This article is just for information and interest about a passing project idea. I had to research x86 assembly, MSDOS debug,  online references, ASCII codes,  opcodes,  HEX etc. before I was capable of even writing the few small programs above to demonstrate my ideas.
 If nothing else I hope you find this article enjoyable and ultimately useful.  As an interesting way to create binary code without any tools, it is pretty cool but I can't really imagine how this technique would be useful in any real situation. I do understand the many system admins still use MSDOS for invaluable scripting requirements so If you manage to find a clever use for any of these hints or tips please drop a comment!

References

ASCII Table
http://www.asciitable.com/

ASCII Table extended
http://www.commfront.com/images/Extended-ASCII-Table.jpg 

MSDOS, BIOS, EMS and Mouse Interrupt lists

http://www.htl-steyr.ac.at/~morg/pcinfo/hardware/interrupts/inte1at0.htm

Intel x86 Assembler Instruction Set Opcode Table
http://sparksandflames.com/files/x86InstructionChart.html

Example assembler program
http://csclab.murraystate.edu/bob.pilgrim/405/x86_assembly.html

Thursday 22 January 2015

Arduino - OLED Module with 3D demo sketch


Arduino Uno compatible OLED 128x64

Recently I bought a small OLED 128x64 screen module for use with my Arduino Uno. The module I chose was based upon a few key requirements. The module had to be cheap, under (£5 GPB), 128x64 screen resolution, work within 3-5volts , I2C compatible, minimum 4 wire setup and not require additional electrical components to get up and running. The module I eventually bought was a Chinese import from Amazon UK.

The module is manufactured by Heltec (Heltec.cn)
0.96 Inch I2C IIC SPI Serial 128 x 64 OLED LCD LED
http://www.amazon.co.uk/dp/B00NHP6HVQ/ref=pe_385721_37038051_TE_3p_dp_1

Wiring the OLED module


The Arduino has two sets of pins allocated to I2C communication.Arduino boards with the R3 layout (1.0 pinout), the SDA (data line) and SCL (clock line) are on the pin headers close to the AREF pin. I used the alternative pins A4 (SDA), A5 (SCL) only to keep the wiring together.

OLED - Arduino Uno
VCC ---> 5V
GND ---> GND
SCL ---> Pin A5
SDA ---> Pin A4

U8G library for graphics

I chose to use the U8GLib library for all necessary graphics functions. The U8GLib examples have lists of Constructors (device drivers) embedded into the code, so matching the module to an appropriate driver was easy. (I initially tried using the Adafruit libraries but had problems getting images to show on the screen).

The library can be downloaded here:
https://code.google.com/p/u8glib/

Installation 

1.  Copy the U8G files to an appropriate Arduino Library folder e.g. 
C:\Program Files\Arduino\libraries\U8glib\
2.  Launch the Arduino application
3.  Copy the 3d wireframe code below into a new sketch.
4.  Upload the sketch to the Arduino and enjoy the spinning 3D cube!

Compilation using the U8G library usually takes a while, so be patient!

Arduino sketch

//3D_Cube for Arduino OLED module by Colin Ord, 9/1/2015
//A port of my original JustBasic Cube_3D demo to the Arduino Uno using U8G library.

#include "U8glib.h"

//The following line will need changing depending on your board type!
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_FAST); // Dev 0, Fast I2C / TWI

float tx, nx, p;
float ty, ny, py;
float rot, rotx, roty, rotz, rotxx, rotyy, rotzz, rotxxx, rotyyy, rotzzz;
int i; //0 to 360
int fl, scale; //focal length
int wireframe[12][2];

int originx = 64;
int originy = 32; //32

int front_depth = 20;
int back_depth = -20;

//Store cube vertices
int cube_vertex[8][3] = {
{ -20, -20, front_depth},
{20, -20, front_depth},
{20, 20, front_depth},
{ -20, 20, front_depth},
{ -20, -20, back_depth},
{20, -20, back_depth},
{20, 20, back_depth},
{ -20, 20, back_depth}
};

int fd = 0; //0=orthographic

void setup(void)
{
u8g.begin();

//Clear Screen
u8g.firstPage();
do {
// empty screen
} while ( u8g.nextPage() );
}

void draw_vertices(void)
{
u8g.drawPixel (rotxxx, rotyyy);
}

void draw_wireframe(void)
{
u8g.drawLine(wireframe[0][0], wireframe[0][1], wireframe[1][0], wireframe[1][1]);
u8g.drawLine(wireframe[1][0], wireframe[1][1], wireframe[2][0], wireframe[2][1]);
u8g.drawLine(wireframe[2][0], wireframe[2][1], wireframe[3][0], wireframe[3][1]);
u8g.drawLine(wireframe[3][0], wireframe[3][1], wireframe[0][0], wireframe[0][1]);

//cross face above
u8g.drawLine(wireframe[1][0], wireframe[1][1], wireframe[3][0], wireframe[3][1]);
u8g.drawLine(wireframe[0][0], wireframe[0][1], wireframe[2][0], wireframe[2][1]);

u8g.drawLine(wireframe[4][0], wireframe[4][1], wireframe[5][0], wireframe[5][1]);
u8g.drawLine(wireframe[5][0], wireframe[5][1], wireframe[6][0], wireframe[6][1]);
u8g.drawLine(wireframe[6][0], wireframe[6][1], wireframe[7][0], wireframe[7][1]);
u8g.drawLine(wireframe[7][0], wireframe[7][1], wireframe[4][0], wireframe[4][1]);

u8g.drawLine(wireframe[0][0], wireframe[0][1], wireframe[4][0], wireframe[4][1]);
u8g.drawLine(wireframe[1][0], wireframe[1][1], wireframe[5][0], wireframe[5][1]);
u8g.drawLine(wireframe[2][0], wireframe[2][1], wireframe[6][0], wireframe[6][1]);
u8g.drawLine(wireframe[3][0], wireframe[3][1], wireframe[7][0], wireframe[7][1]);
}

void loop(void)
{
//picture loop
for (int angle = 0; angle <= 360; angle = angle + 3) {
u8g.firstPage();
do {
for (int i = 0; i < 8; i++) {

rot = angle * 0.0174532; //0.0174532 = one degree
//rotateY
rotz = cube_vertex[i][2] * cos(rot) - cube_vertex[i][0] * sin(rot);
rotx = cube_vertex[i][2] * sin(rot) + cube_vertex[i][0] * cos(rot);
roty = cube_vertex[i][1];
//rotateX
rotyy = roty * cos(rot) - rotz * sin(rot);
rotzz = roty * sin(rot) + rotz * cos(rot);
rotxx = rotx;
//rotateZ
rotxxx = rotxx * cos(rot) - rotyy * sin(rot);
rotyyy = rotxx * sin(rot) + rotyy * cos(rot);
rotzzz = rotzz;

//orthographic projection
rotxxx = rotxxx + originx;
rotyyy = rotyyy + originy;

//store new vertices values for wireframe drawing
wireframe[i][0] = rotxxx;
wireframe[i][1] = rotyyy;
wireframe[i][2] = rotzzz;

draw_vertices();
}

draw_wireframe();

} while (u8g.nextPage());
}
}