• Home
  • About
  • Coulombs law

    Yesterday I was playing around with some real electronics, but today I have been playing with some the simulation of electrostatic particles.

    attraction_0082.png

    I'm using Coulomps law to create hundred particles which have a charge. In the center of these particles there's the center of gravity. All particles are attracted to this center point, but they also keep a distance from each other based on the their chage and the force I calculate using Coulomb's law. Note that this is a my implementation of Coulomb's law, where I use 10 for the constant which you can change if you want more or less attraction.

    float c = 10.0 * charge * pMagnet->getCharge() / (r*r);
    ofxVec3f dir_tmp = dir;
    float aa = c/mass;
    dir_tmp.normalize().scale(aa);
     
    velocity.x += dir_tmp.x;
    velocity.y += dir_tmp.y;

    So in short this effect is created in 3 simple steps:

    • Loop over all particles and let each particle move towards or away from all the other particles based on Coulombs law.
    • When all particles have reacted on the other particles using the Coulombs law, we gravitate towards a center particle. I'm only using the center particle to get the position of it, so I know towards I need to attract it. It's important that we add a bit of simple drag in this gravitate() function (like velocity *= 0.96) as we want to particles to come to rest slowly. Without this drag the particles will bounce around only.
    • Then the last step is to update the position of the particles (position += velocity) and that's it.

    Continue reading if you want to see the source of my particle class.

    4 April 2010

    Read more
  • Womby 0.1

    Together with Bas Pijls, we're working on a simple prototype shield for the Arduino. With our shield, code-named Womby, you can use your Arduino to program another AVR chip. We're using an Attiny2313. You can use this board, for example, when you're working on a project where you need more than one arduino/avr.

    Using this board you can program as much attinies as you want and use those in your project. Programming an attiny2313 is kind of similar as programming the Arduino. The nice thing about this design is that you can create your own "arduino" like board for a 10th of the costs. You can also program those nice attiny45.

    3 April 2010

    Read more
  • Photoshop layers to PNG

    I had to export around 100 layers to transparent PNG images and created an addon for Photoshop CS 4 which exports layers to transparent PNG images. There is a export layers script in photoshop by default, though this did not work on my Mac 10.6 as all files were overwritten. Therefore I created a simple addon that does this job.

    How it works

    You create a group with a name like "footer", then in that group you create layers with names like "logo", "counter" etc.. The addon will export the layers to files, which get the name from the group and the layer, so: "footer_logo.png", "footer_counter.png" etc. The addon only works for one level deep layers. So when you don't want to export some layers put them in a 2nd level layer set.

    Installation (Mac, will also work on Windows)

    Download the file below and copy it to your Applications\Adobe Photoshop CS4\Presets\Scripts directory and restart photoshop.

    Download export_layer_to_png.zip

    25 March 2010

    Read more
  • Sphere, particles and billboarding

    Implemented (cheating) billboards into the particle sphere application. While playing the openGL games I'm making some progress. I've attached some screenshots of my current work. All credits should go to Robert Hodging of flight404 as I'm solely trying to rebuild his work to learn openGL.

    20 March 2010

    Read more
  • Brother 2030 toner problem

    A year ago I bought a Brother 2030HL printer... after a year I needed to replace my toner which I did. After printer like 100 pages in 3 months the toner light went on again, indicating I had to replace my toner again. I checked my toner but couldn't find anything strange so I called the tech support which walked me through a couple of steps and tada! I can print again. I went googling and found an other post where someone describes what his tech guy told him. It's a little different as I needed to press 6 times instead of 5......

    17 March 2010

    Read more
  • 3D Billboarding

    Currently I'm reading up on billboarding in openGL. Billboarding is a method to create 3D shapes, mostly QUADS which face the camera so the appear 2D. This technique is used to draw particles for example. To understand billboarding one has to know about openGL rotation matrices, vector math and how openGL projects 3D coordinates to your screen.......

    17 March 2010

    Read more
  • glRotatef

    glRotatef(angle, x,y,z) is used to rotate vertices around the axes defined by x,y,z where the values come from a normalized vector3. I used this to rotated the textures that are drawn into a GL_QUAD on the sphere. I'm talking about the nebula textures. I need to figure out how to rotate the QUAD because I want to draw a couple of nebula images into a quad that is drawn like a billboard (google on opengl billboarding). This creates the foggy effect in this video on Vimeo http://vimeo.com/634725

    15 March 2010

    Read more
  • Sphere and particles

    While learning openGL I try to recreate stunning visualisations I found here, on Vimeo. Now, it's time for flight404. Flight404 videos are awesome! Technically impressive and just beautiful. In this video I've tried to add physics to the particles, which are textured quads, that face the center of a sphere. I've used perlin noise for the motion, added some trails and random forces. I've had some help from Robert, but I'm not sure how he implements his gravitational/magnetism physics. I tried to use Newtons law of gravitation but this didn't gave me the results I wanted. When Roberts video is all magnetism based I definitely want to find out how he did it ;-). Especially if the particles rotate based on attraction. Im using standard Euler based particles and stiff springs to keep the particles on the sphere.

    7 March 2010

    Read more
  • Attiny2313, AVRdude and Arduino & AVRisp

    Today I've tested the avrdude, avrisp and arduino & avrisp toolchain (AAAA-toolchain) to program avr chips, especially the attiny2313 chip. Arduino is a very robust board used in various hardware projects. Using the arduino programming environment you can easily program the chip. With the AAAA-toolchain you can use your arduino board to program other AVR chips. Below I'll describe the steps necessary to program an attiny2313 chip to blink a led.

    What you need

    • arduino ide version 0.018 - download
    • mega-isp version 0.3 - download
    • avrdude version 5.10. Download WinAVR version 2010.01.10 which includes avrdude for windows.

    Installation

    Arduino
    Simply unpack the arduino zip file. Copy the arduino-0018 directory to a place you like, I used C:\Program Files\arduino-0018

    Mega-isp
    Unpack the zip which contains the avrisp.pde file. This is the Arduino project file which you need to burn to your Arduino.

    WinAVR

    • Follow the installation wizard
    • Add the binary path to your system PATH variable. On windows, I used the default installation directory (C:\WinAVR-20100110\bin). By adding this to your PATH environment variable you're able to execute the "avrdude" command from any CMD window, in any path. Google for a description on how to set your PATH environment variable.

    The hardware

    Okay, when you've downloaded and installed all necessary files you're ready to create your circuit. But first some info, so you know what you're doing. Using the AAAA-toolchain you use the arduino to program another AVR chip. The arduino uses ICSP (in circuit serial programming) for this. Basically this means that you need to connect a couple of wires from the arduino to your AVR chip (attiny2313). We need to connect the standard MOSI, MISO, SCK, RST wires for ICSP. Use this wiring:

    Programming wires

    ArduinoAttiny2313
    Pin 10 Pin 1 - RST
    Pin 11Pin 17 - MOSI
    Pin 12Pin 18 - MISO
    Pin 13Pin 19 - SCK
    Vcc (+5V)Pin 20 - Vcc
    GndPin 10

    Prepping the Arduino

    Start the Arduino IDE and open the avrisp.pde file you downloaded before. Connect your Arduino, select the correct board and COM port and upload the avr-isp code to the arduino. I'll not explain this more thoroughly as it's basic arduino programming. When you've uploaded avrisp to the arduino you're ready to create the "hello world", blinking led application to test this avr-isp programming method.

    Programming the attiny2313

    When you want to program your attiny2313, you need to understand that we use different steps to get the program-code on the chip. To program the attiny2313 you need to use "avrdude", which is also used by Arduino (under the hood, if I'm correct). AVRDude is able to put the program-code on the chip using the avrisp programming method. WinAVR is set of tools you need to program an attiny (or other avr) without Arduino, using avrdude. The steps you need to take are:

    ● write the application code in C
    ● compile the code for the attiny2313 chip using avr-gcc
    ● upload the compiled code (hex file) to your attiny2313 using avrdude

    Application code
    I just googled for a attiny2313 blinking led example that I'll use. Connect pin 12 of your attiny2313 to a led with a current limiting resistor. Copy and paste this code in a file named blinking_led_2313.c.

    #define F_CPU 1000000UL
    #include <avr/io.h>
    #include <util/delay.h>
     
    int main(void) {
        DDRB |= 1<<PB0; /* set PB0 to output */
        while(1) {
            PORTB &= ~(1<<PB0); /* LED on */
            _delay_ms(100);
            PORTB |= 1<<PB0; /* LED off */
            _delay_ms(900);
        }
        return 0;
    }

    Compile the code to a hex file
    Create a new file in the same directory of your blinking_led_2313.c file with the name "Makefile" and put this code in it (see below). You can easily reuse this makefile for other projects by changing the "PRJSRC" variable.

    # See: http://electrons.psychogenic.com/modules/arms/view.php?w=art&idx=8&page=2
    ##### This Makefile will make compiling Atmel AVR 
    ##### micro controller projects simple with Linux 
    ##### or other Unix workstations and the AVR-GCC 
    ##### tools.
    #####
    ##### It supports C, C++ and Assembly source files.
    #####
    ##### Customize the values as indicated below and :
    ##### make
    ##### make disasm 
    ##### make stats 
    ##### make hex
    ##### make writeflash
    ##### make gdbinit
    ##### or make clean
    #####
    ##### See the http://electrons.psychogenic.com/ 
    ##### website for detailed instructions
     
     
    ####################################################
    #####                                          #####
    #####              Configuration               #####
    #####                                          #####
    ##### Customize the values in this section for #####
    ##### your project. MCU, PROJECTNAME and       #####
    ##### PRJSRC must be setup for all projects,   #####
    ##### the remaining variables are only         #####
    ##### relevant to those needing additional     #####
    ##### include dirs or libraries and those      #####
    ##### who wish to use the avrdude programmer   #####
    #####                                          #####
    ##### See http://electrons.psychogenic.com/    #####
    ##### for further details.                     #####
    #####                                          #####
    ####################################################
     
     
    #####         Target Specific Details          #####
    #####     Customize these for your project     #####
     
    # Name of target controller 
    # (e.g. 'at90s8515', see the available avr-gcc mmcu 
    # options for possible values)
    MCU=attiny2313
     
    # Name of our project
    # (use a single word, e.g. 'myproject')
    PROJECTNAME=blinking_led_2313
     
    # Source files
    # List C/C++/Assembly source files:
    # (list all files to compile, e.g. 'a.c b.cpp as.S'):
    # Use .cc, .cpp or .C suffix for C++ files, use .S 
    # (NOT .s !!!) for assembly source code files.
    PRJSRC=blinking_led_2313.c
     
    # additional includes (e.g. -I/path/to/mydir)
    INC=
     
    # libraries to link in (e.g. -lmylib)
    LIBS=
     
    # Optimization level, 
    # use s (size opt), 1, 2, 3 or 0 (off)
    OPTLEVEL=s
     
     
    #####      AVR Dude 'writeflash' options       #####
    #####  If you are using the avrdude program
    #####  (http://www.bsdhome.com/avrdude/) to write
    #####  to the MCU, you can set the following config
    #####  options and use 'make writeflash' to program
    #####  the device.
     
     
    # programmer id--check the avrdude for complete list
    # of available opts.  These should include stk500,
    # avr910, avrisp, bsd, pony and more.  Set this to
    # one of the valid "-c PROGRAMMER-ID" values 
    # described in the avrdude info page.
    # 
    AVRDUDE_PROGRAMMERID=avrisp
     
    # port--serial or parallel port to which your 
    # hardware programmer is attached
    #
    AVRDUDE_PORT=com12
     
     
    ####################################################
    #####                Config Done               #####
    #####                                          #####
    ##### You should not need to edit anything      #####
    ##### below to use the makefile but may wish   #####
    ##### to override a few of the flags           #####
    ##### nonetheless                              #####
    #####                                          #####
    ####################################################
     
     
    ##### Flags ####
     
    # HEXFORMAT -- format for .hex file output
    HEXFORMAT=ihex
     
    # compiler
    CFLAGS=-I. $(INC) -g -mmcu=$(MCU) -O$(OPTLEVEL) \
        -fpack-struct -fshort-enums             \
        -funsigned-bitfields -funsigned-char    \
        -Wall -Wstrict-prototypes               \
        -Wa,-ahlms=$(firstword                  \
        $(filter %.lst, $(<:.c=.lst)))
     
    # c++ specific flags
    CPPFLAGS=-fno-exceptions               \
        -Wa,-ahlms=$(firstword         \
        $(filter %.lst, $(<:.cpp=.lst))\
        $(filter %.lst, $(<:.cc=.lst)) \
        $(filter %.lst, $(<:.C=.lst)))
     
    # assembler
    ASMFLAGS =-I. $(INC) -mmcu=$(MCU)        \
        -x assembler-with-cpp            \
        -Wa,-gstabs,-ahlms=$(firstword   \
            $(<:.S=.lst) $(<.s=.lst))
     
     
    # linker
    LDFLAGS=-Wl,-Map,$(TRG).map -mmcu=$(MCU) \
        -lm $(LIBS)
     
    ##### executables ####
    CC=avr-gcc
    OBJCOPY=avr-objcopy
    OBJDUMP=avr-objdump
    SIZE=avr-size
    AVRDUDE=avrdude
    REMOVE=rm -f
     
    ##### automatic target names ####
    TRG=$(PROJECTNAME).out
    DUMPTRG=$(PROJECTNAME).s
     
    HEXROMTRG=$(PROJECTNAME).hex 
    HEXTRG=$(HEXROMTRG) $(PROJECTNAME).ee.hex
    GDBINITFILE=gdbinit-$(PROJECTNAME)
     
    # Define all object files.
     
    # Start by splitting source files by type
    #  C++
    CPPFILES=$(filter %.cpp, $(PRJSRC))
    CCFILES=$(filter %.cc, $(PRJSRC))
    BIGCFILES=$(filter %.C, $(PRJSRC))
    #  C
    CFILES=$(filter %.c, $(PRJSRC))
    #  Assembly
    ASMFILES=$(filter %.S, $(PRJSRC))
     
     
    # List all object files we need to create
    OBJDEPS=$(CFILES:.c=.o)    \
        $(CPPFILES:.cpp=.o)\
        $(BIGCFILES:.C=.o) \
        $(CCFILES:.cc=.o)  \
        $(ASMFILES:.S=.o)
     
    # Define all lst files.
    LST=$(filter %.lst, $(OBJDEPS:.o=.lst))
     
    # All the possible generated assembly 
    # files (.s files)
    GENASMFILES=$(filter %.s, $(OBJDEPS:.o=.s)) 
     
     
    .SUFFIXES : .c .cc .cpp .C .o .out .s .S \
        .hex .ee.hex .h .hh .hpp
     
     
    .PHONY: writeflash clean stats gdbinit stats
     
    # Make targets:
    # all, disasm, stats, hex, writeflash/install, clean
    all: $(TRG)
     
    disasm: $(DUMPTRG) stats
     
    stats: $(TRG)
        $(OBJDUMP) -h $(TRG)
        $(SIZE) $(TRG) 
     
    hex: $(HEXTRG)
     
     
    writeflash: hex
        $(AVRDUDE) -c $(AVRDUDE_PROGRAMMERID)   \
         -p $(MCU) -P $(AVRDUDE_PORT) -e        \
         -b 19200 \
         -U flash:w:$(HEXROMTRG)
     
    install: writeflash
     
    $(DUMPTRG): $(TRG) 
        $(OBJDUMP) -S  $< > $@
     
     
    $(TRG): $(OBJDEPS) 
        $(CC) $(LDFLAGS) -o $(TRG) $(OBJDEPS)
     
     
    #### Generating assembly ####
    # asm from C
    %.s: %.c
        $(CC) -S $(CFLAGS) $< -o $@
     
    # asm from (hand coded) asm
    %.s: %.S
        $(CC) -S $(ASMFLAGS) $< > $@
     
     
    # asm from C++
    .cpp.s .cc.s .C.s :
        $(CC) -S $(CFLAGS) $(CPPFLAGS) $< -o $@
     
     
     
    #### Generating object files ####
    # object from C
    .c.o: 
        $(CC) $(CFLAGS) -c $<
     
     
    # object from C++ (.cc, .cpp, .C files)
    .cc.o .cpp.o .C.o :
        $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
     
    # object from asm
    .S.o :
        $(CC) $(ASMFLAGS) -c $< -o $@
     
     
    #### Generating hex files ####
    # hex files from elf
    #####  Generating a gdb initialisation file    #####
    .out.hex:
        $(OBJCOPY) -j .text                    \
            -j .data                       \
            -O $(HEXFORMAT) $< $@
     
    .out.ee.hex:
        $(OBJCOPY) -j .eeprom                  \
            --change-section-lma .eeprom=0 \
            -O $(HEXFORMAT) $< $@
     
     
    #####  Generating a gdb initialisation file    #####
    ##### Use by launching simulavr and avr-gdb:   #####
    #####   avr-gdb -x gdbinit-myproject           #####
    gdbinit: $(GDBINITFILE)
     
    $(GDBINITFILE): $(TRG)
        @echo "file $(TRG)" > $(GDBINITFILE)
     
        @echo "target remote localhost:1212" \
                            >> $(GDBINITFILE)
     
        @echo "load"        >> $(GDBINITFILE) 
        @echo "break main"  >> $(GDBINITFILE)
        @echo "continue"    >> $(GDBINITFILE)
        @echo
        @echo "Use 'avr-gdb -x $(GDBINITFILE)'"
     
     
    #### Cleanup ####
    clean:
        $(REMOVE) $(TRG) $(TRG).map $(DUMPTRG)
        $(REMOVE) $(OBJDEPS)
        $(REMOVE) $(LST) $(GDBINITFILE)
        $(REMOVE) $(GENASMFILES)
        $(REMOVE) $(HEXTRG)
     
     
     
    #####                    EOF                   #####

    After you've created this Makefile in the same directory as your blinking_led_2313.c file, open a CMD window and go to that directory where the makefile is located. Then type make (but be sure you've closed the Arduino-IDE before doing so!!).

    Upload the code to the chip

    In the same CMD window type: make install and you should see a blinking LED in a couple of seconds.

    Some helpfull links

    http://dddanmar.net/
    blinking led

    Extra

    MCU names for avr-gcc

    avr2
    at90s2313
    at90s2323
    at90s2333
    at90s2343
    attiny22
    attiny26
    at90s4414
    at90s4433
    at90s4434
    at90s8515
    at90c8534
    at90s8535
    at86rf401
    attiny13
    attiny2313
    avr3
    atmega103
    atmega603
    at43usb320
    at43usb355
    at76c711
    avr4
    atmega8
    atmega48
    atmega88
    atmega8515
    atmega8535
    avr5
    atmega16
    atmega161
    atmega162
    atmega163
    atmega165
    atmega168
    atmega169
    atmega32
    atmega323
    atmega325
    atmega3250
    atmega64
    atmega645
    atmega6450
    atmega128
    at90can128
    at94k
    avr1
    at90s1200
    attiny11
    attiny12
    attiny15
    attiny28

    4 March 2010

    Read more
  • 3D Math

    I've been reading up with 3D math, openGL, physics etc.. for a while now and yes, finally I think I'm getting somewhere. The first results, although still extremely basic, but quite fun are ready to be shown. I've created a sphere from ofxVec3f objects (3d vector objects, in C++), which get randomly distributed using a simple spatial algorithm.

    Then, after I've calculated the positions for the points I create rectangles, actually just openGL GL_QUADS, but using the crossproduct to get the perpendicular lines/positions that make up de quad. When I've got the positions of the QUADs I use an alpha transparent image and put that as a texture on it.

    Calculating the points for the quad
    Below is the code I've used to calculate the vertices for the QUAD. I'm not sure if this is the best solution, but it works perfect!

    void TestQuad::draw() {
        ofEnableAlphaBlending();
     
     
        glBegin(GL_LINE_STRIP);
        for(int i = 0; i < tail.size(); ++i) {
            float a = ((float)tail.size()-i)/(float)tail.size() * .2;
            glColor4f(1.0, 0.0, 0.6,a);
            glVertex3f(tail.at(i).x, tail.at(i).y, tail.at(i).z);
        }
        glEnd();
     
        ofxVec3f normal = position - center;
        ofxVec3f up_vec(0,1,0);
        ofxVec3f p1 = normal.getCrossed(up_vec).normalize().scale(size);
        ofxVec3f p2 = normal.getCrossed(p1).normalize().scale(size);
        ofxVec3f p3 = normal.getCrossed(p2).normalize().scale(size);
        ofxVec3f p4 = normal.getCrossed(p3).normalize().scale(size);
        ofxVec3f pp1 = position+p1;
        ofxVec3f pp2 = position+p2;
        ofxVec3f pp3 = position+p3;
        ofxVec3f pp4 = position+p4;
     
     
        glColor4f(1.0,1.0,1.0,0.9f);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,texture_id);
     
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 0.0f); glVertex3f(pp1.x, pp1.y, pp1.z);
            glTexCoord2f(1.0f, 0.0f); glVertex3f(pp2.x, pp2.y, pp2.z);
            glTexCoord2f(1.0f, 1.0f); glVertex3f(pp3.x, pp3.y, pp3.z);
            glTexCoord2f(0.0f, 1.0f); glVertex3f(pp4.x, pp4.y, pp4.z); 
        glEnd();
        glDisable(GL_TEXTURE_2D);
    }

    Distributing points on a sphere

    // from: http://local.wasp.uwa.edu.au/~pbourke/geometry/spherepoints/
    #include "stdio.h"
    #include "stdlib.h"
    #include "math.h"
     
    /*
       Create N points on a sphere aproximately equi-distant from each other
       Basically, N points are randomly placed on the sphere and then moved
       around until then moved around until the minimal distance between the
       closed two points is minimaised.
       Paul Bourke, July 1996
    */
     
    #define ABS(x) (x < 0 ? -(x) : (x))
     
    typedef struct {
      double x,y,z;
    } XYZ;
     
    void Normalise(XYZ *,double);
    double Distance(XYZ,XYZ);
     
    /*
       Called with three arguments, the number of points to distribute, the
       radius of the sphere, and the maximum number of iterations to perform.
    */
    int main(argc,argv)
    int argc;
    char **argv;
    {
       int i,j,n;
       int counter = 0,countmax = 100;
       int minp1,minp2;
       double r,d,mind,maxd;
       XYZ p[1000],p1,p2;
     
       /* Check we have the right number of arguments */
       if (argc < 4) {
          fprintf(stderr,"Usage: %s npoints radius niterations\n",argv[0]);
          exit(0);
       }
       if ((n = atoi(argv[1])) < 2)
          n = 3;
       if ((r = atof(argv[2])) < 0.001)
          r = 0.001;
       if ((countmax = atoi(argv[3])) < 100)
          countmax = 100;
     
       /* Create the initial random cloud */
       for (i=0;i<n;i++) {
           p[i].x = (rand()%1000)-500;
           p[i].y = (rand()%1000)-500;
           p[i].z = (rand()%1000)-500;
           Normalise(&p[i],r);
        }
     
        while (counter < countmax) {
     
            /* Find the closest two points */
            minp1 = 0;
            minp2 = 1;
            mind = Distance(p[minp1],p[minp2]);
            maxd = mind;
            for (i=0;i<n-1;i++) {
                for (j=i+1;j<n;j++) {
                    if ((d = Distance(p[i],p[j])) < mind) {
                       mind = d;
                       minp1 = i;
                       minp2 = j;
                    }
                    if (d > maxd)
                       maxd = d;
                }
            }
     
            /*
               Move the two minimal points apart, in this case by 1%
               but should really vary this for refinement
            */
            p1 = p[minp1];
            p2 = p[minp2];
            p[minp2].x = p1.x + 1.01 * (p2.x - p1.x);
            p[minp2].y = p1.y + 1.01 * (p2.y - p1.y);
            p[minp2].z = p1.z + 1.01 * (p2.z - p1.z);
            p[minp1].x = p1.x - 0.01 * (p2.x - p1.x);
            p[minp1].y = p1.y - 0.01 * (p2.y - p1.y);
            p[minp1].z = p1.z - 0.01 * (p2.z - p1.z);
            Normalise(&p[minp1],r);
            Normalise(&p[minp2],r);
     
            counter++;
        }
     
        /* Write out the points in your favorite format */
     
    }
     
    void Normalise(p,r)
    XYZ *p;
    double r;
    {
       double l;
     
       l = r / sqrt(p->x*p->x + p->y*p->y + p->z*p->z);
       p->x *= l;
       p->y *= l;
       p->z *= l;
    }
     
    double Distance(p1,p2)
    XYZ p1,p2;
    {
       XYZ p;
     
       p.x = p1.x - p2.x;
       p.y = p1.y - p2.y;
       p.z = p1.z - p2.z;
       return(sqrt(p.x*p.x + p.y*p.y + p.z*p.z));
    }

    14 February 2010

    Read more
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9