Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

  • 3D/Binaural audio mixing

    https://youtube.com/watch?v=nLJzY2LE4g0

    Click the link above for a small demo of what is described below. Please wear headphones!

    What is this?

    This is a small example scene showcasing some code I've written for positioning sound sources in 3D space around the listener (the sketch actually starts when you see the head - at the start you Audacity to illustrate how panning affects the mono signal (and that it's truly mono)). The sound sources are just mono audio files which are represented by the sphere rotating around a human's head. You can place them anywhere in the space and animate them as well (currently just by hand) to rotate around the listener. The project makes extensive use of the Minim library and extends some of the unit generators, notably adding a Convolver and FadeIn/FadeOut.

    How it works?

    The code is based on an HRIR database provided by CIPIC. Essentially, our ears work as a filter that shapes the incoming sound - this alteration of the sound can be captured via an impulse response which we call head related impulse response. We can use this HRIR data to convolve it with the original sound source and so make it sound as if it is coming from a certain position. A HRIR database per subject can contain thousands of points of data - CIPIC provides us with 1250 points per point cloud (1250 positions), and almost 50 subjects. These points are collected at the same distance from the head's "center." The demo above demonstrates the use of HRIR for Subject 003, but there are two things to note: 1. We have different ears and so filter the sound differently. Hence why there are so many subjects when collecting data. Studies have shown, though, that you can learn how to localize sounds using someone else's ears over 2-3 weeks, which is pretty cool since you keep them in memory! 2. There is a limited amount of points in the point cloud, but an unlimited amount of positions. What we are doing here is using Delaunay triangulation (with some custom tinkering) to create a kind of a spherical mesh from which we could interpolate data based on into which triangle our defined point falls into where the vertices of that triangle are 3 know HRIR measurements - in such a way, we can cover quite well all the points in 3D space around the person.

    Where is it going and why the post here?

    I am looking to expand this to firstly include all the subjects from CIPIC and then add more functionality to also include the distance and different trajectories plus rendering so the files could be easily saved. I am using Processing to both quickly prototype and learn about this subject and while it may very well happen that at some point it will leave Processing and even get rewritten in another language, I am quite interested to hear from the community if there would be interest to add this as a library to Processing, along with all the upcoming results of experiments? The project already extends the Minim audio library a fair bit and I was considering sending the new ugens to Minim as well - I will quite likely build upon them a lot more, but if properly wrapped up they could be useful to others.

    Who am I?

    I'm a second-year computer science and music student. I have quite a lot of random programming experience mostly in Unity using c# but never ventured into programming for audio. Now that it is pretty much a part of my degree, I decided to tackle making a "virtual" binaural microphone, since I have made physical ones in the past and using a combination of both forms a part of my final year project!

  • How do I draw in a zoom mode on a small section of image?

    @koogs meant to say unfolding maps :-B

    If you use PGraphics, then when you zoom in/out, you will need to calculate the transformations for positions as well. For example, mouse position will need to be mapped. I believe you should be able to find related posts in the forum: https://forum.processing.org/two/search?Search=panning

    There is a Mouse 2D Transformations that does some mouse transformations for you after you translate, scale and rotate your image. You can install it using the Lib manager in Processing and check the provided examples.

    Kf

  • Fly over a heightmap-generated landscape

    There is another approach. Use the camera() function as described in the reference. Then, you will move the eye and the center coordinates by the same amount. This is the version of panning along an axis in 3D.

    Thxs for sharing your solution btw!

    Kf

  • how to zoom in zoom out

    Please format your code. Edit your post (gear on top right side of any of your posts), select your code and hit ctrl+o. Leave an empty line above and below your block of code.

    Check

    https://forum.processing.org/two/search?Search=panning

    Kf

  • Having issues with dragging when creating a map

    Hi there, I'm brand new to processing and programming in general and am currently taking a data visualization course and having trouble with one of the exercises so was hoping I could maybe get some guidance here. We are tasked with creating a map of the college with panning and zooming functions on the mouse and also with the keyboard. I currently have zooming and panning working with the mouse decently however my map continuously gets off center if I drag one way or the other and then zoom out, its often shifted from its default location where I would like it to be constant. I cant quite figure out what is causing the problem though I'm assuming the issue is in my mousedragged function but I really cant seem to figure out with my limited knowledge. Some of the code for panning and zooming was given to us when starting the exercise so because I did not originally write it I think I'm having issues there as well as the fact the original example had the campus image taking up the entire window where I have a small inset map that is using a quarter of the window. Any help would be greatly appreciated. I'm brand new to this forum so not sure about formatting so I apologize if it is not correct. I have also linked the image I am using at the end. Thanks!

    //Define the aerial vars
    PImage aerial;
    
    int imgW;
    int imgH;
    int miniW;
    int miniH;
    
    int centerX;
    int centerY;
    int miniX;
    int miniY;
    
    //Control Box
    int boxW;
    int boxH;
    int boxX;
    int boxY;
    
    //Define the zoom vars
    int scale = 1;
    int maxScale = 10;
    float zoomFactor = 0.4;
    
    //Define the pan vars
    int panFromX;
    int panFromY;
    
    int panToX;
    int panToY;
    
    int xShift = 0;
    int yShift = 0;
    
    int direction = 1;
    
    void setup() {
      aerial = loadImage("Campus100dpi.png");
     //Aerial Map
      imgW = aerial.width;
      imgH = aerial.height;
      centerX = imgW / 2;
      centerY = imgH / 2;
    
      //Inset Map
      miniW = aerial.width / 3;
      miniH = aerial.height / 3;
      miniX = width - 200;
      miniY = height - height ;
    
      //Control Box
      boxW = width / 3;
      boxH = height;
      boxX = width - 200;
      boxY = height / 3;
    
      size(800, 450);
    }
    
    void draw(){
      background(0);
      imageMode(CENTER);
      image(aerial, centerX, centerY, imgW, imgH);
      imageMode(CORNER);
      image(aerial, miniX, miniY, miniW, miniH);
      fill(0);
      rect(boxX, boxY, boxW, boxH);
    
    }
    
    //Pan function
    void mousePressed(){
      if(mouseButton == LEFT){
        panFromX = mouseX;
        panFromY = mouseY;
      }
    }
    
    //Pan function continued..
    void mouseDragged(){
      if(mouseButton == LEFT){
        panToX = mouseX;
        panToY = mouseY;
    
        xShift = panToX - panFromX;
        yShift = panToY - panFromY;
    
        //Only pan with the image occupies the whole display
        if(centerX - imgW / 2 <= 0
        && centerX + imgW / 2 >= width
        && centerY - imgH / 2 <= 0
        && centerY + imgH / 2 >= height){
          centerX = centerX + xShift;
          centerY = centerY + yShift;
        }
    
        //Set the constraints for pan
        if(centerX - imgW / 2 > 0){
          centerX = imgW / 2;
        }
    
        if(centerX + imgW / 2 < width){
          centerX = width - imgW / 2;
        }
    
        if(centerY - imgH / 2 > 0){
          centerY = imgH / 2;
        }
    
        if(centerY + imgH / 2 < height){
          centerY = height - imgH / 2;
        }
    
        panFromX = panToX;
        panFromY = panToY;
      }
    }
    
    //Zoom function
    void mouseWheel(MouseEvent event) {
      float e = event.getAmount();
    
      //Zoom in
      if(e == -1){
        if(scale < maxScale){
          scale++;
          imgW = int(imgW * (1+zoomFactor));
          imgH = int(imgH * (1+zoomFactor));
    
          int oldCenterX = centerX;
          int oldCenterY = centerY;
    
          centerX = centerX - int(zoomFactor * (mouseX - centerX));
          centerY = centerY - int(zoomFactor * (mouseY - centerY));
        }
      }
    
      //Zoom out
      if(e == 1){
        if(scale < 1){
          scale = 1;
          imgW = aerial.width;
          imgH = aerial.height;
        }
    
        if(scale > 1){
          scale--;
          imgH = int(imgH/(1+zoomFactor));
          imgW = int(imgW/(1+zoomFactor));
    
          int oldCenterX = centerX;
          int oldCenterY = centerY;
    
          centerX = centerX + int((mouseX - centerX)
          * (zoomFactor/(zoomFactor + 1)));
          centerY = centerY + int((mouseY - centerY)
          * (zoomFactor/(zoomFactor + 1)));
    
          if(centerX - imgW / 2 > 0){
            centerX = imgW / 2;
          }
    
          if(centerX + imgW / 2 < width){
          //  centerX = width - imgW / 2;
          }
    
          if(centerY - imgH / 2 > 0){
            centerY = imgH / 2;
          }
    
          if(centerY + imgH / 2 < height){
           // centerY = height - imgH / 2;
          }
        }
      }
    }
    

    Campus100dpi

  • p5.js code feedback/critique

    I made this keyboard and Source and is not particulary fast, but kind of works. In order to avoid retriggering when you hold down a key, I make an array for the triggered notes, make a copy of that array and then delete the original array and fill it again with the new keys. I then check if the newly triggered keys are also in the previously triggered array and if, so don't play them.

    Is there a way to optimize the performance of this and make it work on desktops without touch?

    Any hints greatly appreciated.

    var keyboard,       //image of the keyboard
        kbdcopy,        //resized image of the keyboard (visible)
        keycolormap,    //colormap of the keys (hidden)
        imageRatio,     //ratio of the image h/w    
        keyboardWidth,  
        //keyboardHeight,
        keysdown = new Array(),
        previouskeysdown = new Array(),
        scaleFactor = 1;    //scaling factor of the image
    
    const FOLDER = 'keys/', EXT = '.wav',
          INDEX_START = 53, INDEX_END = 79,
          INDEX_TOTAL = 1 + INDEX_END - INDEX_START,
          sounds = Array(INDEX_TOTAL);
    
    //sounds.playMode(restart); // for some reason this throws an error even though it's in the sound.p5,js reference
    
    function preload() {
        for (let i = 0; i < INDEX_TOTAL; ++i){
            sounds[i] = loadSound(FOLDER + (i + INDEX_START) + EXT);
        }
        keyboard=loadImage("keyboard.png", img => kbdcopy = img.get());
        keycolormap=loadImage("keycolormap.png");
    }
    
    function setup()   {
        var myCanvas = createCanvas(windowWidth, windowHeight);
        myCanvas.parent("keyboard");
        colorMode(RGB, 255);
        imageRatio = keyboard.height/keyboard.width;
        //print("imageRatio: "+imageRatio);
        windowResized();
      }
    
    function draw() {
        background(255);
        image(kbdcopy,0,0);
        textSize(17);
        fill(150);
        text("TinyKeys v.0.13 Max Neupert, 2017",10,kbdcopy.height+25);
    //    text("touches: "+touches.length,10,kbdcopy.height+45);
    //    text("keysdown: ",10,kbdcopy.height+65);
    //    for (var i=0;i<keysdown.length;i++){
    //        text(keysdown[i]+",",100+(i*26),kbdcopy.height+65);
    //    }
    //        text("previouskeysdown: ",10,kbdcopy.height+85);
    //    for (var i=0;i<previouskeysdown.length;i++){
    //        text(previouskeysdown[i]+",",160+(i*26),kbdcopy.height+85);
    //    }
        touching();
        playing();
        muting();
    }
    
    function windowResized() {
        resizeCanvas(windowWidth, windowHeight);
        if (windowWidth < keyboard.width){
            kbdcopy = keyboard.get();
            kbdcopy.resize(windowWidth,0);
            keyboardWidth = windowWidth;
            //keyboardHeight = keyboardWidth*imageRatio;
            scaleFactor = keyboardWidth/keyboard.width;
            //print("new scaleFactor: "+scaleFactor);
            }
    }
    
    // INTERACTION AND SOUND PLAYING
    
    function touchStarted(){}  //an empty function to stop the default behavior of panning screen
    
    // TOUCH
    function touching(){
        var note;
        //var midi;
        fill(255,100,50,100);
        noStroke();
        previouskeysdown = [];
        arrayCopy(keysdown,previouskeysdown); //copy old array
        keysdown = []; //delete old array
        for (let i = 0; i < touches.length; i++) {
            ellipse(touches[i].x, touches[i].y, 85)
            note=keycolormap.get(touches[i].x/scaleFactor,touches[i].y/scaleFactor); //get the color in the hidden image
            note=((red(note))/5);
            //midi = note+52
            note = note-1;
            if (note>-1){
                keysdown.push(note);
            }
        }
        if (touches.length==0){
             keysdown = [];
            }
    }
    
    function playing(){
        var note;
        for (let i = 0; i <keysdown.length; i++){
                note=keysdown[i];
                    if (previouskeysdown.includes(keysdown[i])){ //check if the key was previosly touched
                        // well, if so, don't trigger again then (empty if clause...)
                    }
                    else{
                        sounds[note].setVolume(0.5);
                        sounds[note].play(); // if it is a new touch, well then play.
                    } 
    
        }
    }
    function muting(){
        var note;
        for (let i = 0; i <previouskeysdown.length; i++){
                note=previouskeysdown[i];
                    if (previouskeysdown.includes(keysdown[i])){ //check if the key was previosly touched
                        // well, if so, then keep it playing (empty if clause...)
                    }
                    else{
                        sounds[note].fade(0,0.1);
                        sounds[note].stop(0.1); // if it is not touched any more, then stop.
                    } 
    
        }
    }
    
  • createGraphic bigger than canvas

    Please format your code. Edit your post (gear on top right side of any of your posts), select your code and hit ctrl+o. Leave an empty line above and below your block of code.

    ****EDIT: Also check these prev discussions: https://forum.processing.org/two/search?Search=panning

    Kf

  • Finding intersection between two polygons

    @quark It's not going to be unrestricted but at this point I can't say how many shapes or vertices yet. Approximately maybe 15 shapes and average of 10 points each (differs for each shape).

    The vertex data are stored as an array of objects in the form:

    [{
      x: 1.002,
      y: 4.815
    },{
      ...
    }]
    

    No panning or zooming.

    I've just traced the call stack and found square roots and arc tangents. They seemed like some polar coordinates conversion of some sorts, didn't decipher the algorithm myself.

  • How do i zoom relative to mouse position?

    Also your uranus_ link is broken. It should read

    addObject("SKYBLUE", 301, "m", "https://"+"upload.wikimedia.org/wikipedia/commons/e/ea/Uranus_%28Edited%29.jpg");

    Check this post by the way: https://forum.processing.org/two/discussion/20813/zooming-and-panning-headache#latest

    Kf

  • the BACK key ?

    @kfrajer It's a lot of data for a music app. Lots of note data, with all sorts of controls for volume, panning, synth settings etc. I use a byte[] because when I started the Table didn't exist ... it is on my list of things to do to make use of it though.

    @akenaton Thanks once more for your code. I think I will leave this for now though...I have a solution now that works and it sounds as if using the callbacks in Processing is incomplete or buggy!

  • Approach to utilise variable data from Draw

    You can try outside of draw... but where? Inside draw, you can trigger than when your avg position changed by more than, say, 15 pixels, you can trigger the panning. What you need is a global variable. Something like this below (partial code):

    int globalX;
    boolean trigger=false;
    void draw(){
      avgX=...;
      avgY=...;
      if(abs(gloablX-avgX)>15)
         trigger=true;  //Trigger panning update
      gloablX=avgX;   //Update globalX position... you can do the same for Y
    
      ....
    
      if(trigger==true){
         //update your sin pan property
         trigger=false;  // Don't forget to reset your trigger
      }
    
    }
    

    However, I still think everything is happening inside draw. You don't need to instantiate an object every frame. Instead, you update your created object with a new pan value.

    Kf

  • Approach to utilise variable data from Draw

    of course, thank you!

    a large part of this sketch is from a processing tutorial about colour tracking. Using this sketch, I am able to assign a target colour, and have Processing render a ellipse around it and track it across the screen. You can see Dans example of this at his youtube link.

    My goal was to take that tracking point, use (or map) its x axis to a variable, than I can use to control the panning functions of a sine wave.

    I can achieve this crudely by assigning the sine wave code INTO the drawing window

          sine = new SinOsc(this);
          sine.pan(map(avgX, 0, width, -1.0, 1.0));
          sine.play();
    

    When it is in the drawing window, avgX is obtaining the value from the main detection algorithm (which i believe is computed at the last moment of this section).

    void draw() {
      video.loadPixels();
      image(video, 0, 0);
    
      //threshold = map(mouseX, 0, width, 0, 100);
      threshold = 20;
    
      float avgX = 0;
      float avgY = 0;
    
      int count = 0;
    
      // Begin loop to walk through every pixel
      for (int x = 0; x < video.width; x++ ) {
        for (int y = 0; y < video.height; y++ ) {
          int loc = x + y * video.width;
          // What is current color
          color currentColor = video.pixels[loc];
          float r1 = red(currentColor);
          float g1 = green(currentColor);
          float b1 = blue(currentColor);
          float r2 = red(trackColor);
          float g2 = green(trackColor);
          float b2 = blue(trackColor);
    
          float d = distSq(r1, g1, b1, r2, g2, b2); 
    
          if (d < threshold*threshold) {
            stroke(255);
            strokeWeight(1);
            point(x, y);
            avgX += x;
            avgY += y;
            count++;
          }
        }
      }
    
      // We only consider the color found if its color distance is less than 10. 
      // This threshold of 10 is arbitrary and you can adjust this number depending on how accurate you require the tracking to be.
      if (count > 0) { 
        avgX = avgX / count;
        avgY = avgY / count;
        // Draw a circle at the tracked pixel
        fill(255);
        strokeWeight(4.0);
        stroke(0);
        ellipse(avgX, avgY, 24, 24);
    
    
      }
    }
    
    float distSq(float x1, float y1, float z1, float x2, float y2, float z2) {
      float d = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) +(z2-z1)*(z2-z1);
      return d;
    
    }
    

    The problem with running the code like this, is that processing does not like the sine wave command being in the draw window, and crashes the runtime in around 5 seconds or so (but works great until then!)

    So, I need to get the x co-ordinate of the ellipse I am drawing, and map and assign that to a new variable to control the pan aspect. Though, I can't figure out how to get that computed number from the DRAW section, so I can use it with my sine wav.

    Hope that helps,

    Matt

  • Approach to utilise variable data from Draw

    Hello! New to Processing and have been experimenting with the tutorials and videos a bit, and have a hit a hurdle I am sure someone will have some insight to.

    Essentially, I am trying to take the colour tracking algorithm from Tutorial 11.5, and utilise the avgX variable to control the panning of a sine wave. My code is below...

    // Daniel Shiffman
    // http://codingtra.in
    // http://patreon.com/codingtrain
    // Code for: 
    
    import processing.video.*;
    import processing.sound.*;
    
    SinOsc sine;
    Capture video;
    
    color trackColor; 
    float threshold = 25;
    
    void setup() {
      size(640, 360);
      String[] cameras = Capture.list();
      //printArray(cameras);
      video = new Capture(this, cameras[3]);
      video.start();
      trackColor = color(255, 0, 0);
    }
    
    void captureEvent(Capture video) {
      video.read();
    }
    
    void draw() {
      video.loadPixels();
      image(video, 0, 0);
    
      //threshold = map(mouseX, 0, width, 0, 100);
      threshold = 20;
    
      float avgX = 0;
      float avgY = 0;
    
      int count = 0;
    
      // Begin loop to walk through every pixel
      for (int x = 0; x < video.width; x++ ) {
        for (int y = 0; y < video.height; y++ ) {
          int loc = x + y * video.width;
          // What is current color
          color currentColor = video.pixels[loc];
          float r1 = red(currentColor);
          float g1 = green(currentColor);
          float b1 = blue(currentColor);
          float r2 = red(trackColor);
          float g2 = green(trackColor);
          float b2 = blue(trackColor);
    
          float d = distSq(r1, g1, b1, r2, g2, b2); 
    
          if (d < threshold*threshold) {
            stroke(255);
            strokeWeight(1);
            point(x, y);
            avgX += x;
            avgY += y;
            count++;
          }
        }
      }
    
      // We only consider the color found if its color distance is less than 10. 
      // This threshold of 10 is arbitrary and you can adjust this number depending on how accurate you require the tracking to be.
      if (count > 0) { 
        avgX = avgX / count;
        avgY = avgY / count;
        // Draw a circle at the tracked pixel
        fill(255);
        strokeWeight(4.0);
        stroke(0);
        ellipse(avgX, avgY, 24, 24);
    
    
      }
    }
    
    float distSq(float x1, float y1, float z1, float x2, float y2, float z2) {
      float d = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) +(z2-z1)*(z2-z1);
      return d;
    
    }
    
    void mousePressed() {
      // Save color where the mouse is clicked in trackColor variable
      int loc = mouseX + mouseY*video.width;
      trackColor = video.pixels[loc];
    }
      {
          sine = new SinOsc(this);
          sine.pan(map(avgX, 0, width, -1.0, 1.0));
          sine.play();
    }  
    

    The problem is that the variable avgX cannot exist outside the draw. It works if I place the Oscillator in Draw, but that causes a crash in a hurry!

    Any help greatly appreciated!

    Best, Matt

  • GSoC Proposal Concept - p5.js.Sound

    Hello-- I am interested in working on p5.js.sound. I would break my idea down into three stages (I am not yet sure if it is feasible to propose all three as one summer project). Any thoughts and feedback would be greatly appreciated!

    proposal can be viewed:

    https://docs.google.com/document/d/1fC-ZSMrVdsF4MUCxuMoRKNp7_Jx_iXjqxSJM9oT0eC8/edit?usp=sharing

    1) Develop EQ and Compression objects (based on Web Audio nodes). Potentially add 3D panning into soundfile object

    2) Design presets for effects and create Instruments (presets based on Oscillators)

    3) A library of modules for algorithmic composition. Programmers would be able to adjust parameters of these modules to generate evolving compositions.

    I think these ideas make sense as a proposal for Processing because they fit the goal that the language should make things appear on the screen as quickly as possible. These additions to the sound library will be useful for musicians and non-musicians alike- for the former will have a fuller toolset to play with while creating visuals, and the latter will be able to easily produce interesting and non-repetitive sounds as they experiment.

    I kept the descriptions brief but let me know if anything is unclear! Many thanks in advance.

  • scrolling image larger than window through portion of window

    https://processing.org/reference/image_.html

    In the reference, you want to use the alternative version on image() with 5 parameters, then you can draw your image in a selected section of your sketch.

    For moving a section of the image, you need to use a PGraphics object. Or you can search in the forum for panning.

    Kf

  • Slippy Maps on p5.js

    Edit your post. Select your code. Hit ctrl+o. Make sure there is an empty line above and below your code.

    For the static case, yes, there are several links offered by the mapbox API. When you are editing your map, click in create a static map and then you will be able to copy the link. You know that you have the right link when you see the latitude and longitude info in the last part of the link, exactly as in shiffman's video.

    For dynamic panning and zooming, it will take some additional effort and to become familiar with the API. I can't promise anything on my side at the moment because I have my hands full. Get the static version working first.

    Kf

  • Slippy Maps on p5.js

    Is the zooming done by loading another image from their website, assuming you are using mapbox? Or are you applying zooming by scaling your sketch? For the former, you need to keep track of the center of your map and the zoom factor of you loaded map image. Then the web marcator functions will take care of the correct positioning of your points in your sketch (yes, you need to keep using translate and any geocoordinate to be offset from the center as illustrated in the video). On the other hand, if you are using scaling functions applied to an image, then you need to look into previous post related to panning: https://forum.processing.org/two/search?Search=panning
    Also:
    https://forum.processing.org/two/discussion/20445/resize-sketch-window https://forum.processing.org/two/discussion/comment/86915#Comment_86915

    Related to how to insert mapbox into a p5.js, it is a described in the video. Did you try it?

    I just used the info on this video in another post: https://forum.processing.org/two/discussion/21135/add-latitude-longitude-to-csv-file-and-make-interactive-map-with-the-data/p1

    Kf

  • Prompting the user to input numbers

    Another option instead of asking for an user input which requires typing, you could just retrieve the coordinate from the actual mouse position. For example, one could generate a mouse click event, then one would get the current mouse position. This strategy fails if, for example, your sketch has GUI elements (buttons, slide bars, etc) and you need to click there in those sampe positions or in case you have a sketch where your image/background has panning action. An alternative solution is to capture the mouse position by pressing the space bar.

    Kf

  • Collision detection - why not working properly?

    Hi @djevazi

    For debugging your code, you could disable peasyCam by commenting any reference to it. Then more people will be able to run your code.

    I have changed your code a bit. You can check the changes but you don't have to stick to them. You will see the problem can be solved by changing one line in your code which I explain below. The main change I did in your code was to migrate the tripoint() function to your Triangle class. The second big change was to introduce a smart printing tool for your case. I call it verbose and it works like this. When you want to get information, you press the space key. The space key will call the tripoint function associated to each triangle and in turn, it will print the areas involved in the calculation.

    Now, the problem of your code is in this line area1 + area2 + area3 == areaOrig. If we were doing the calculations on paper, this will work all the time. The problem is rounding. You will see that when the mouse is inside the triangle, your comparison can be off by 1/1000 and this is enough to throw your calculations off. Most of the time, rounding off errors comes from divisions. Calculating your areas do not involve division! I believe the rounding error comes from using screenX() and screenY() functions. Ok, so now the solution is what I quoted as VERSION 2 below in the code. I changed the comparison to abs(area1 + area2 + area3 - areaOrig) < epsilon. This statement performs the same comparison as before. However, this time, it allows for an error in the comparison. How big of an error is ok? As big as defined by the value of epsilon. I chose epsilon to be 0.01 You will notice that and epsilon of probably 0.005 or even 0.002 (aka. 5 times smaller) is enough when peasyCam is disabled. However, when peasyCam is enabled, you will see that the error in the comparison increases because panning/zooming/rotations of your perspective affects the screenX/Y() functions. From my test, I can see that 0.01 could not be enough for you. You might have to allow for a larger error. Notice than increasing epsilon can remove your blinking problem inside your triangle completely. But there is a side effect. When the mouse pointer is closer to the triangle but not inside, it can be detected as a hit. So there is a trade off and that is for you to explore.

    Kf

        import peasy.*;
        PeasyCam jcam;
        boolean verbose=false;
    
        ArrayList <Point> points = new ArrayList <Point>();
        ArrayList <Triangle> triangles = new ArrayList <Triangle>();
    
        void setup()
        {
          size(800, 800, P3D);
          smooth();
          //jcam = new PeasyCam(this, 200);
    
          color tempColore=color(255, 255, 255);
    
          PVector v1= new PVector(0, 0, 0);
          Point pt1 = new Point(v1, tempColore);
          points.add(pt1);
    
          PVector v2= new PVector(100, 0, 0);
          Point pt2 = new Point(v2, tempColore);
          points.add(pt2);
    
          PVector v3= new PVector(0, 100, 0);
          Point pt3 = new Point(v3, tempColore);
          points.add(pt3);
    
          PVector v4= new PVector(100, 0, 0);
          Point pt4 = new Point(v4, tempColore);
          points.add(pt4);  
    
          PVector v5= new PVector(100, 100, 0);
          Point pt5 = new Point(v5, tempColore);
          points.add(pt5);
    
          PVector v6= new PVector(0, 100, 0);
          Point pt6 = new Point(v6, tempColore);
          points.add(pt6);
    
    
          //triangles initialize
          for (int i=0; i<points.size(); i=i+3)
          {
            Triangle tr = new Triangle(points.get(i).pos, points.get(i+1).pos, points.get(i+2).pos);
            triangles.add(tr);
          }
        }
    
    
    
    
        void draw()
        {
          background(150);
    
          for (Triangle tria : triangles)
          { 
            color tempColore=0;
    
    
    
            boolean hit = tria.triPoint(mouseX, mouseY);
    
            if (hit==true)
            {
              tempColore = #A57066;
              //println("hit");
            } else
            {
              tempColore = #CEBE9A;
              //println("no hit");
            }
            tria.display(tempColore);
          }
    
    
          for (int i = points.size ()-1; i >= 0; i--)
          { 
            points.get(i).display();
          }
        }
    
        void keyPressed() {
          if (key==' ')
            verbose=!verbose;
    
          if (verbose==true) {
    
            for (Triangle tria : triangles)
             tria.triPoint(mouseX, mouseY);
             println("........");
    
              verbose=false;
            }
          }
    
    
          class Point
          {
            PVector pos;
            color colore;
    
    
            Point(PVector posIn, color coloreIn)
            {
              pos = posIn;
              colore=coloreIn;
            }
    
            void display()
            {
              colorMode(RGB);
              noStroke();
              fill(colore);
              pushMatrix();
              translate(pos.x, pos.y, pos.z);
              box(1);
              popMatrix();
            }
          }
    
    
          class Triangle
          {
            PVector A, B, C;
            color colore;
    
            Triangle (PVector Ain, PVector Bin, PVector Cin)
            {
              A=Ain;
              B=Bin;
              C=Cin;
            }
    
            void display(color coloreIn)
            {
              colore = coloreIn;
              fill(colore);
              beginShape(TRIANGLE);
              stroke(255, 20);
              strokeWeight(2);
              vertex(A.x, A.y, A.z);
              vertex(B.x, B.y, B.z);
              vertex(C.x, C.y, C.z);
              endShape();
            }
    
            private boolean triPoint(float x1, float y1, float x2, float y2, float x3, float y3, float mx, float my) 
            {
              // get the area of the triangle
              float areaOrig = abs( (x2-x1)*(y3-y1) - (x3-x1)*(y2-y1) );
    
              // get the area of 3 triangles made between the point
              // and the corners of the triangle
              float area1 =    abs( (x1-mx)*(y2-my) - (x2-mx)*(y1-my) );
              float area2 =    abs( (x2-mx)*(y3-my) - (x3-mx)*(y2-my) );
              float area3 =    abs( (x3-mx)*(y1-my) - (x1-mx)*(y3-my) );
    
              if (verbose==true) println("Check " +(area1 + area2 + area3 == areaOrig) + " left "+(area1 + area2 + area3)+" right="+areaOrig);
    
              // if the sum of the three areas equals the original,
              // we're inside the triangle!
              boolean point_inside_triangle_check=area1 + area2 + area3 == areaOrig;  //VERSION ONE
    
              float epsilon=0.01;
              point_inside_triangle_check = abs(area1 + area2 + area3 - areaOrig)<epsilon;  //VERSION TWO
    
    
              if (point_inside_triangle_check) 
              {
                return true;
              }
              return false;
            }
    
            boolean triPoint(int _mx, int _my) {
    
              float ax = screenX(A.x, A.y);
              float ay = screenY(A.x, A.y);
              float bx = screenX(B.x, B.y);
              float by = screenY(B.x, B.y);
              float cx = screenX(C.x, C.y);
              float cy = screenY(C.x, C.y);
    
    
              return triPoint(ax, ay, bx, by, cx, cy, _mx, _my);
            }
          }