Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
|
Nama is a soft circuit instrument that has open purpose and usage, being able to be freely folded, twisted, tightened and manipulated in various contexts to generate real time digital data of its movement.
Based on the concept of relational object created by Lygia Clark, the interface is built upon a fabric tissue given its physical particularities that, through its interaction in motion, are able to bring to senses characteristics related to virtuality such as: fluidity, flexibility and mobility. Therefore causing, along with the sensible feedback, a non-verbal and kinesthetic understanding of virtual liquidity.
The current setup of the interface has a single Lilypad Arduino, 5 Lilypad Accelerometers, one Xbee Module, and a LiPo battery sewed altogether manually with conductive thread. Data is gathered by the accelerometers and sent wirelessly to a computer through Arduino and Xbee, where they will be reprocessed into some kind of output. The project also includes a customizable software specially designed to receive the data from the interface.
DocumentationA video that demonstrates its potential:
And below, a video documentation of an interactive installation produced based on the instrument:
List of materials and components:
- 1 LilyPad Arduino 328 Main Board.
- 5 LilyPad Accelerometers ADXL335.
- 1 LilyPad Xbee.
- LilyPad FTDI Basic Breakout
- 5V LilyPad LiPower.
- 2 XBee 1mW Chip Antenna
- Series 1. - XBee Explorer USB.
- Polymer Lithium Ion Battery (LiPo)
- 1000mAh (good up to 8h running).
- LiPo Charger Basic
- Micro-USB.
- Conductive Thread
- 234/34 4ply.
- Needle set.
- Fabric of your choice.
- Thin wire + solder (optional).
- Textile glue + mounting tape (optional)
More info at:
///////////////////////////////////////////////////////////////
// Nama Project v1.0
// Instrument Arduino code.
// ------------------------------------------------------------
// Created by Luiz Zanotello on May/2012.
// Under Creative Commons License: CC BY-NC-SA 3.0.
// More information at: http://www.viraseres.com/nama
///////////////////////////////////////////////////////////////
//Accelerometer 1 (z) - bottom right
////////////////////////////////////
const int a1pinV = 6; //output current pin
const int a1pinZ = A0; //data pin
//Accelerometer 2 (z) - top right
/////////////////////////////////
const int a2pinV = 7; //output current pi
const int a2pinZ = A1; //data pin
//Central accelerometer (x/y)
/////////////////////////////
const int aCpinV = 8; //output current pi
const int aCpinX = A2; //data pin
const int aCpinY = A3; //data pin
//Accelerometer 3 (z) - top left
////////////////////////////////
const int a3pinV = 2; //output current pi
const int a3pinZ = A4; //data pin
//Accelerometer 4 (z) - bottom left
///////////////////////////////////
const int a4pinV = 3; //output current pi
const int a4pinZ = A5; //data pin
////////////////////////////////////////////////////////
void setup()
{
//Begin serial transmition:
Serial.begin(115200);
//Set output pins (+ current):
pinMode(a1pinV, OUTPUT);
digitalWrite(a1pinV, HIGH);
pinMode(a2pinV, OUTPUT);
digitalWrite(a2pinV, HIGH);
pinMode(aCpinV, OUTPUT);
digitalWrite(aCpinV, HIGH);
pinMode(a3pinV, OUTPUT);
digitalWrite(a3pinV, HIGH);
pinMode(a4pinV, OUTPUT);
digitalWrite(a4pinV, HIGH);
}
////////////////////////////////////////////////////////
void loop()
{
// Printing analog data received from accelerometers
Serial.println();
Serial.print(5); // Number of accelerometers
Serial.print(',');
Serial.print(analogRead(a1pinZ)); // Accelerometer 1 reading (z)
Serial.print(',');
Serial.print(analogRead(a2pinZ)); // Accelerometer 2 reading (z)
Serial.print(',');
Serial.print(analogRead(a3pinZ)); // Accelerometer 3 reading (z)
Serial.print(',');
Serial.print(analogRead(a4pinZ)); // Accelerometer 4 reading (z)
Serial.print(',');
Serial.print(analogRead(aCpinX)); // Central accelerometer reading (x)
Serial.print(',');
Serial.print(analogRead(aCpinY)); // Central accelerometer reading (y)
Serial.print(tranG);
delay(10);
}
////////////////////////////////////////////////////////
Processing Code
Java//////////////////////////////////////////////////////////////////////////////////////////////
// Nama Project v1.0
// Instrument data receiver.
// -------------------------------------------------------------------------------------------
// All codes created by Luiz Zanotello on May/2012.
// Under Creative Commons License: CC BY-NC-SA 3.0.
// More information at: http://www.viraseres.com/nama
//////////////////////////////////////////////////////////////////////////////////////////////
// General configuration
int baudRate = 115200; //Baud rate
int serialPort = 0; //Serial port
boolean isPrinting = true; //Print to post?
// Libraries
import processing.serial.*;
import processing.opengl.*;
//////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
size(1200, 600, OPENGL);
beginSerial();
setupFonts();
smooth();
}
void draw() {
background(230, 230, 212);
visualizeData();
if (isPrinting==true) {
printValues();
}
}
void printValues() {
println("AC NAME / RAW / FILTERED / DIFFERENCE / FILTERED DIFFERENCE");
println("A1(z): "+acData[1][0]+" / "+acData[1][1]+" / "+acData[1][2]+" / "+acData[1][3]);
println("A2(z): "+acData[2][0]+" / "+acData[2][1]+" / "+acData[2][2]+" / "+acData[2][3]);
println("A3(z): "+acData[3][0]+" / "+acData[3][1]+" / "+acData[3][2]+" / "+acData[3][3]);
println("A4(z): "+acData[4][0]+" / "+acData[4][1]+" / "+acData[4][2]+" / "+acData[4][3]);
println("A5(x): "+acData[5][0]+" / "+acData[5][1]+" / "+acData[5][2]+" / "+acData[5][3]);
println("A5(y): "+acData[6][0]+" / "+acData[6][1]+" / "+acData[6][2]+" / "+acData[6][3]);
println("AV(z): "+acData[0][0]+" / "+acData[0][1]+" / "+acData[0][2]+" / "+acData[0][3]);
println();
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Kalman Filter Class.
// Created by Interactive Matter.
// (http://github.com/interactive-matter/Processing/tree/master/lis302dl_kalman)
// -------------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////////
public class KalmanFilter {
private float q;
private float r;
private float x;
private float p;
private float k;
public KalmanFilter(float q, float r, float p, float initial_value) {
this.q=q;
this.r=r;
this.p=p;
this.x=initial_value;
}
public float addSample(float measurement) {
//omit x=x
p=p+q;
k=p/(p+r);
x= x + k*(measurement-x);
p=(1-k)*p;
return x;
}
public String toString() {
return "KalmanFilter with p="+p+", k="+k;
}
public float getQ() {
return q;
}
public float getR() {
return r;
}
public float getP() {
return p;
}
public float getK() {
return k;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Serial communication and configuration to the Lilypad accelerometer soft circuit.
// -------------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////////
// Use the following variables to calibrate the readings from the accelerometers.
// Change the "low" and "high" values of each accelerometer
// according to the average lowest and highest values received.
int a1lowZ = 307;
int a1highZ = 759;
int a2lowZ = 294;
int a2highZ = 727;
int a3lowZ = 281;
int a3highZ = 711;
int a4lowZ = 286;
int a4highZ = 717;
int a5lowX = 303;
int a5highX = 769;
int a5lowY = 298;
int a5highY = 747;
//////////////////////////////////////////////////////////////////////////////////////////////
// Mapping variables
Serial myPort;
float acData[][] = new float[7][4]; // [raw, filt, dif, dif filt] [average z, 1, 2, 3, 4, 5x, 5y, 5z]
float acDataOld[] = new float[7]; // used for calculating the differences
float newValue, newValueFiltered, masterAverage, newDif, rawDif; //mapping
// Kalman filter instances
// q(process noise), r(sensor noise), p(estimated error), initial_value
KalmanFilter filterDif0 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif1 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif2 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif3 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif4 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif5 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif6 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif7 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterA1 = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA2 = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA3 = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA4 = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA5X = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA5Y = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterMaster = new KalmanFilter(0.5, 256, 100, 510);
//////////////////////////////////////////////////////////////////////////////////////////////
// Serial Event
void beginSerial() {
myPort = new Serial(this, Serial.list()[serialPort], baudRate);
myPort.bufferUntil(10);
}
// Map Data
void serialEvent(Serial p) {
String inString;
try {
inString = (myPort.readString());
if (inString != null) {
String[] listSt = split(inString, ',');
if (listSt.length == 7) {
masterAverage = 0;
//////////////////////
// Accelerometer 1 - Z
newValue = float(listSt[1]);
if (Float.isNaN(newValue)) {
newValue = acData[1][0];
}
acData[1][0] = newValue;
masterAverage = masterAverage+newValue;
newValueFiltered = constrain(map(filterA1.addSample(newValue), a1lowZ, a1highZ, 0.01, 1.0), 0.001, 2.0);
if (Float.isNaN(newValueFiltered)) {
newValueFiltered = acData[1][1];
}
acData[1][1] = newValueFiltered;
//////////////////////
// Accelerometer 2 - Z
newValue = float(listSt[2]);
if (Float.isNaN(newValue)) {
newValue = acData[2][0];
}
acData[2][0] = newValue;
masterAverage = masterAverage+newValue;
newValueFiltered = constrain(map(filterA2.addSample(newValue), a2lowZ, a2highZ, 0.01, 1.0), 0.001, 2.0);
if (Float.isNaN(newValueFiltered)) {
newValueFiltered = acData[2][1];
}
acData[2][1] = newValueFiltered;
//////////////////////
// Accelerometer 3 - Z
newValue = float(listSt[3]);
if (Float.isNaN(newValue)) {
newValue = acData[3][0];
}
acData[3][0] = newValue;
masterAverage = masterAverage+newValue;
newValueFiltered = constrain(map(filterA3.addSample(newValue), a3lowZ, a3highZ, 0.01, 1.0), 0.001, 2.0);
if (Float.isNaN(newValueFiltered)) {
newValueFiltered = acData[3][1];
}
acData[3][1] = newValueFiltered;
//////////////////////
// Accelerometer 4 - Z
newValue = float(listSt[4]);
if (Float.isNaN(newValue)) {
newValue = acData[4][0];
}
acData[4][0] = newValue;
masterAverage = masterAverage+newValue;
newValueFiltered = constrain(map(filterA4.addSample(newValue), a4lowZ, a4highZ, 0.01, 1.0), 0.001, 2.0);
if (Float.isNaN(newValueFiltered)) {
newValueFiltered = acData[4][1];
}
acData[4][1] = newValueFiltered;
//////////////////////
// Accelerometer C - X
newValue = float(listSt[5]);
if (Float.isNaN(newValue)) {
newValue = acData[5][0];
}
acData[5][0] = newValue;
newValueFiltered = constrain(map(filterA5X.addSample(newValue), a5lowX, a5highX, 0.01, 1.0), 0.001, 2.0);
if (Float.isNaN(newValueFiltered)) {
newValueFiltered = acData[5][1];
}
acData[5][1] = newValueFiltered;
//////////////////////
// Accelerometer C - Y
newValue = float(listSt[6]);
if (Float.isNaN(newValue)) {
newValue =acData[6][0];
}
acData[6][0] = newValue;
newValueFiltered = constrain(map(filterA5Y.addSample(newValue), a5lowY, a5highY, 0.01, 1.0), 0.001, 2.0);
if (Float.isNaN(newValueFiltered)) {
newValueFiltered = acData[6][1];
}
acData[6][1] = newValueFiltered;
//////////////////////
// Master average calc
newValue = masterAverage/4;
if (Float.isNaN(newValue)) {
newValue = acData[0][0];
}
acData[0][0] = newValue;
newValueFiltered = constrain(map(filterMaster.addSample(newValue), (a4lowZ+a3lowZ+a2lowZ+a1lowZ)*0.25, (a4highZ+a3highZ+a2highZ+a1highZ)*0.25, 0.01, 1.0), 0.001, 2.0);
if (Float.isNaN(newValueFiltered)) {
newValueFiltered = acData[0][1];
}
acData[0][1] = newValueFiltered;
setDifferences();
}
}
}
catch(Exception e) {
println(e);
}
}
// Set differences
void setDifferences() {
for (int i=0;i<acData.length;i++) {
acData[i][2] = acData[i][1]-acDataOld[i];
if (i==0) {
acData[i][3] = filterDif0.addSample(acData[i][2]);
}
if (i==1) {
acData[i][3] = filterDif1.addSample(acData[i][2]);
}
if (i==2) {
acData[i][3] = filterDif2.addSample(acData[i][2]);
}
if (i==3) {
acData[i][3] = filterDif3.addSample(acData[i][2]);
}
if (i==4) {
acData[i][3] = filterDif4.addSample(acData[i][2]);
}
if (i==5) {
acData[i][3] = filterDif5.addSample(acData[i][2]);
}
if (i==6) {
acData[i][3] = filterDif6.addSample(acData[i][2]);
}
if (Float.isNaN(acData[i][3])) {
acData[i][3] = acDataOld[i];
}
if (acData[i][3]<0.0001) {
acData[i][3]=0;
}
if (acData[i][2]<0.0001) {
acData[i][2]=0;
}
acDataOld[i] = acData[i][1];
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Graphical visualization of the interface data.
// -------------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////////
// Config
int interfaceDimensionX = 128;
int interfaceDimensionY = 134;
// Mapping variables
PFont titleFont, contentFont, copyrightFont;
float goPoint[][] = new float[5][3];
float baseX, baseY;
void setupFonts() {
titleFont = loadFont("ArialNarrow-23.vlw");
contentFont = loadFont("Courier-15.vlw");
copyrightFont = loadFont("Courier-9.vlw");
}
void visualizeData() {
// Bg
fill(35, 41, 44);
rect(-2, -2, 380, height+4);
// Base position of text
baseX = 60;
baseY = 214;
// Title
textFont(titleFont);
fill(230, 230, 212);
text("Nama Instrument v1.0", baseX-6, baseY-60);
textFont(contentFont);
fill(230, 230, 212);
text("", baseX-6, baseY-28);
textFont(copyrightFont);
text("ACC: RAW FILTER DIF DIF+FILTER", baseX-6, baseY);
// 1
baseY = baseY+34;
textFont(titleFont);
fill(215, 102, 124);
text("A1z: ", baseX-6, baseY);
fill(230, 230, 212);
textFont(contentFont);
text(int(acData[1][0]), baseX+48, baseY-3);
text("", baseX+79, baseY-3);
text(acData[1][1], baseX+84, baseY-3);
text("", baseX+142, baseY-3);
text(acData[1][2], baseX+147, baseY-3);
text("", baseX+205, baseY-3);
text(acData[1][3], baseX+210, baseY-3);
// 2
baseY = baseY+34;
textFont(titleFont);
fill(215, 181, 102);
text("A2z: ", baseX-6, baseY);
fill(230, 230, 212);
textFont(contentFont);
text(int(acData[2][0]), baseX+48, baseY-3);
text("", baseX+79, baseY-3);
text(acData[2][1], baseX+84, baseY-3);
text("", baseX+142, baseY-3);
text(acData[2][2], baseX+147, baseY-3);
text("", baseX+205, baseY-3);
text(acData[2][3], baseX+210, baseY-3);
// 3
baseY = baseY+34;
textFont(titleFont);
fill(102, 215, 161);
text("A3z: ", baseX-6, baseY);
fill(230, 230, 212);
textFont(contentFont);
text(int(acData[3][0]), baseX+48, baseY-3);
text("", baseX+79, baseY-3);
text(acData[3][1], baseX+84, baseY-3);
text("", baseX+142, baseY-3);
text(acData[3][2], baseX+147, baseY-3);
text("", baseX+205, baseY-3);
text(acData[3][3], baseX+210, baseY-3);
// 4
baseY = baseY+34;
textFont(titleFont);
fill(102, 130, 215);
text("A4z: ", baseX-6, baseY);
fill(230, 230, 212);
textFont(contentFont);
text(int(acData[4][0]), baseX+48, baseY-3);
text("", baseX+79, baseY-3);
text(acData[4][1], baseX+84, baseY-3);
text("", baseX+142, baseY-3);
text(acData[4][2], baseX+147, baseY-3);
text("", baseX+205, baseY-3);
text(acData[4][3], baseX+210, baseY-3);
// 5x
baseY = baseY+34;
textFont(titleFont);
fill(139, 137, 127);
text("A5x: ", baseX-6, baseY);
fill(230, 230, 212);
textFont(contentFont);
text(int(acData[5][0]), baseX+48, baseY-3);
text("", baseX+79, baseY-3);
text(acData[5][1], baseX+84, baseY-3);
text("", baseX+142, baseY-3);
text(acData[5][2], baseX+147, baseY-3);
text("", baseX+205, baseY-3);
text(acData[5][3], baseX+210, baseY-3);
// 5y
baseY = baseY+34;
textFont(titleFont);
fill(139, 137, 127);
text("A5y: ", baseX-6, baseY);
fill(230, 230, 212);
textFont(contentFont);
text(int(acData[6][0]), baseX+48, baseY-3);
text("", baseX+79, baseY-3);
text(acData[6][1], baseX+84, baseY-3);
text("", baseX+142, baseY-3);
text(acData[6][2], baseX+147, baseY-3);
text("", baseX+205, baseY-3);
text(acData[6][3], baseX+210, baseY-3);
// separador
baseY = baseY+34;
textFont(contentFont);
fill(230, 230, 212);
text("", baseX-6, baseY-3);
// Average
baseY = baseY+34;
textFont(titleFont);
fill(230, 230, 212);
text("AVz: ", baseX-6, baseY);
fill(230, 230, 212);
textFont(contentFont);
text(int(acData[0][0]), baseX+48, baseY-3);
text("", baseX+79, baseY-3);
text(acData[0][1], baseX+84, baseY-3);
text("", baseX+142, baseY-3);
text(acData[0][2], baseX+147, baseY-3);
text("", baseX+205, baseY-3);
text(acData[0][3], baseX+210, baseY-3);
// Credits
textFont(copyrightFont);
fill(35, 41, 44);
text("created by luiz gustavo zanotello at jun/2012", width-233, height-30);
text("http://www.viraseres.com/nama", width-154, height-20);
text("under CC BY-NC-SA 3.0", width-114, height-10);
////////////////////////////////////////////////////////////////////////////////////////////
// Graph
noStroke();
fill(255);
baseX = width-width/3+map(acData[5][1], 0, 1, -1, 1)*100;
baseY = height/2+map(acData[6][1], 0, 1, -1, 1)*100+map(acData[0][1], 0, 1, -1, 1)*50;
translate(baseX, baseY, map(acData[0][1], 0, 1, 50, -100));
perspective();
rotateX(radians(acData[5][1]*360));
rotateY(radians(acData[6][1]*360));
rotateZ(radians(acData[0][1]*360));
directionalLight(120, 120, 120, 0, -1, -1);
ambientLight(230, 230, 230);
// 4
fill(142-(acData[2][3]*255*100), 170-(acData[2][3]*255*100), 255-(acData[2][3]*255*100), 90+(acData[4][3]*255*100));
goPoint[4][0] = 0-interfaceDimensionX+map(acData[4][1], 0, 1, -100, 100);
goPoint[4][1] = interfaceDimensionY/2+map(acData[4][1], 0, 1, -100, 100);
goPoint[4][2] = map(acData[4][1], 0, 1, -400, 400);
pushMatrix();
translate(goPoint[4][0], goPoint[4][1], goPoint[4][2]);
sphere(6);
popMatrix();
// 3
fill(142-(acData[1][3]*255*100), 255-(acData[1][3]*255*100), 201-(acData[1][3]*255*100), 90+(acData[4][3]*255*100));
goPoint[3][0] = 0-interfaceDimensionX+map(acData[3][1], 0, 1, -100, 100);
goPoint[3][1] = 0-interfaceDimensionY/2+map(acData[3][1], 0, 1, -100, 100);
goPoint[3][2] = map(acData[3][1], 0, 1, -400, 400);
pushMatrix();
translate(goPoint[3][0], goPoint[3][1], goPoint[3][2]);
sphere(6);
popMatrix();
// 2
fill(255-(acData[3][3]*255*100), 221-(acData[3][3]*255*100), 142-(acData[3][3]*255*100), 90+(acData[4][3]*255*100));
goPoint[2][0] = interfaceDimensionX+map(acData[2][1], 0, 1, -100, 100);
goPoint[2][1] = 0-interfaceDimensionY/2+map(acData[2][1], 0, 1, -100, 100);
goPoint[2][2] = map(acData[2][1], 0, 1, -400, 400);
pushMatrix();
translate(goPoint[2][0], goPoint[2][1], goPoint[2][2]);
sphere(6);
popMatrix();
// 1
fill(255-(acData[4][3]*255*100), 142-(acData[4][3]*255*100), 164-(acData[4][3]*255*100), 90+(acData[4][3]*255*100));
goPoint[1][0] = interfaceDimensionX+map(acData[1][1], 0, 1, -100, 100);
goPoint[1][1] = interfaceDimensionY/2+map(acData[1][1], 0, 1, -100, 100);
goPoint[1][2] = map(acData[1][1], 0, 1, -400, 400);
pushMatrix();
translate(goPoint[1][0], goPoint[1][1], goPoint[1][2]);
sphere(6);
popMatrix();
// C
fill(179-(acData[5][3]*255*100)-(acData[6][3]*255*100), 177-(acData[5][3]*255*100)-(acData[6][3]*255*100), 167-(acData[5][3]*255*100)-(acData[6][3]*255*100), 90+(acData[5][3]*255*100)+(acData[6][3]*255*100));
goPoint[0][0] = map(acData[5][1], 0, 1, -400, 400);
goPoint[0][1] = map(acData[6][1], 0, 1, -400, 400);
goPoint[0][2] = map(acData[0][1], 0, 1, -100, 100);
pushMatrix();
translate(goPoint[0][0], goPoint[0][1], goPoint[0][2]);
sphere(6);
popMatrix();
// Lines
stroke(255);
line(goPoint[0][0], goPoint[0][1], goPoint[0][2], goPoint[1][0], goPoint[1][1], goPoint[1][2]);
line(goPoint[0][0], goPoint[0][1], goPoint[0][2], goPoint[2][0], goPoint[2][1], goPoint[2][2]);
line(goPoint[0][0], goPoint[0][1], goPoint[0][2], goPoint[3][0], goPoint[3][1], goPoint[3][2]);
line(goPoint[0][0], goPoint[0][1], goPoint[0][2], goPoint[4][0], goPoint[4][1], goPoint[4][2]);
line(goPoint[1][0], goPoint[1][1], goPoint[1][2], goPoint[2][0], goPoint[2][1], goPoint[2][2]);
line(goPoint[1][0], goPoint[1][1], goPoint[1][2], goPoint[3][0], goPoint[3][1], goPoint[3][2]);
line(goPoint[1][0], goPoint[1][1], goPoint[1][2], goPoint[4][0], goPoint[4][1], goPoint[4][2]);
line(goPoint[2][0], goPoint[2][1], goPoint[2][2], goPoint[3][0], goPoint[3][1], goPoint[3][2]);
line(goPoint[2][0], goPoint[2][1], goPoint[2][2], goPoint[4][0], goPoint[4][1], goPoint[4][2]);
line(goPoint[3][0], goPoint[3][1], goPoint[3][2], goPoint[4][0], goPoint[4][1], goPoint[4][2]);
}
Comments
Please log in or sign up to comment.