Click here to Skip to main content
15,893,668 members
Articles / Programming Languages / C#

Simple Ray Tracing in C# Part VI (Vertex Normal Interpolation)

Rate me:
Please Sign up or sign in to vote.
4.75/5 (26 votes)
15 Jul 2016GPL33 min read 62.1K   70  
An approach to interpolate vertex normals on triangles
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.Windows.Forms;

namespace RayTracer
{
    public class RayTracerThread
    {
        object  m_oCaller;
        int     m_iScreenPixels;
        double  m_fVirtualSize;
        int     m_iRecursivity;
        bool    m_bAntialiasing;
        int     m_iOptimizationGrid;
        List<Material> m_MaterialList;
        List<Object> m_ObjectList;
        rtPoint m_oEye;
        public bool m_bOptimized = true;
        rtPoint m_oRotated;
        rtPoint m_oLight;

        public RayTracerThread(object caller, int iScreenPixels, double fVirtualSize, int iRecursivity, bool bAntialiasing,
            List<Material> MaterialList, List<Object> ObjectList, rtPoint oEye, bool bOptimized, int iOptimizationGrid,
            rtPoint oRotated, rtPoint oLight)
        {
            m_oCaller = caller;
            m_iScreenPixels = iScreenPixels;
            m_fVirtualSize = fVirtualSize;
            m_iRecursivity = iRecursivity;
            m_bAntialiasing = bAntialiasing;
            m_MaterialList = MaterialList;
            m_ObjectList = ObjectList;
            m_oEye = oEye;
            m_oRotated = oRotated;
            m_bOptimized = bOptimized;
            m_iOptimizationGrid = iOptimizationGrid;
            m_oLight = oLight;
        }

        public void CreateThread()
        {
            Thread rtThread = new Thread(new ThreadStart(RayTracing));
            rtThread.Start();
        }

        public void RayTracing()
        {
            Form1 form1 = (Form1)m_oCaller;

            Bitmap newBitmap = new Bitmap(m_iScreenPixels, m_iScreenPixels,
                               PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(newBitmap);
            Rectangle rect = new Rectangle(0, 0, m_iScreenPixels, m_iScreenPixels);
            double fMax = m_fVirtualSize; 
            int rec = m_iRecursivity;  // recursivity 

            RayTracer rayTracer = new RayTracer(rec, m_bOptimized);

            //Object sphere1 = new Object();
            //sphere1.AddSphere(3, 0, -3, 1, mat2, null);
            //rayTracer.AddObject(sphere1);

            foreach(Object oObject in m_ObjectList)
                rayTracer.AddObject(oObject);

            //rtPoint light1 = new rtPoint(0, 0, 4.5);
            rayTracer.AddLight(ref m_oLight);

            rayTracer.RotateAllObjects(m_oRotated.x, m_oRotated.y, m_oRotated.z);
            
            rtPoint color = new rtPoint(0, 0, 0);
            double deltaP = Math.Abs(Algebra.GetCoord(rect.Left,
                                    rect.Right,
                                   -fMax, fMax, rect.Left + 1) + fMax) / 2.0;
            Ray ray = new Ray(null,1);

            ray.m_iLevel = 0;

            ray.target.z = 0.0;
            ray.origin.x = m_oEye.x; ray.origin.y = m_oEye.y; ray.origin.z = m_oEye.z;

            // 
            if(m_bOptimized)
            {
            rayTracer.Initialize(m_iOptimizationGrid, 10*fMax);
            }

            Monitor.Enter(form1);

            form1.CallBack(3, (rect.Right - rect.Left) * (rect.Bottom - rect.Top));

            Monitor.Exit(form1);

            int iCounter = 0;

            for (int i = rect.Left; i < rect.Right; i++)
            {
                double x = Algebra.GetCoord(rect.Left,
                  rect.Right, -fMax, fMax, i);

                for (int j = rect.Top; j < rect.Bottom; j++)
                {
                    double y = Algebra.GetCoord(rect.Top,
                      rect.Bottom, fMax, -fMax, j);

                    ray.target.x = x; ray.target.y = y;

                    color.x = 0; color.y = 0; color.z = 0;

                    if (m_bAntialiasing)
                    {
                        ray.target.x = x - deltaP; ray.target.y =
                             y - deltaP; ray.target.z = 0.0;
                        rtPoint colorA = rayTracer.trace_ray(ray);

                        ray.target.x = x - deltaP; ray.target.y =
                             y + deltaP; ray.target.z = 0.0;
                        rtPoint colorB = rayTracer.trace_ray(ray);

                        ray.target.x = x + deltaP; ray.target.y =
                             y - deltaP; ray.target.z = 0.0;
                        rtPoint colorC = rayTracer.trace_ray(ray);

                        ray.target.x = x + deltaP; ray.target.y =
                             y + deltaP; ray.target.z = 0.0;
                        rtPoint colorD = rayTracer.trace_ray(ray);

                        ray.target.x = x; ray.target.y = y;
                        ray.target.z = 0.0;
                        rtPoint colorE = rayTracer.trace_ray(ray);

                        ray.target.x = x; ray.target.y = y - deltaP;
                        ray.target.z = 0.0;
                        rtPoint colorF = rayTracer.trace_ray(ray);

                        ray.target.x = x; ray.target.y = y + deltaP;
                        ray.target.z = 0.0;
                        rtPoint colorG = rayTracer.trace_ray(ray);

                        ray.target.x = x - deltaP; ray.target.y = y;
                        ray.target.z = 0.0;
                        rtPoint colorH = rayTracer.trace_ray(ray);

                        ray.target.x = x + deltaP; ray.target.y = y;
                        ray.target.z = 0.0;
                        rtPoint colorI = rayTracer.trace_ray(ray);

                        color.x = (colorA.x + colorB.x + colorC.x +
                                   colorD.x + colorE.x + colorF.x +
                                   colorG.x + colorH.x + colorI.x) / 9.0;
                        color.y = (colorA.y + colorB.y + colorC.y +
                                   colorD.y + colorE.y + colorF.y +
                                   colorG.y + colorH.y + colorI.y) / 9.0;
                        color.z = (colorA.z + colorB.z + colorC.z +
                                   colorD.z + colorE.z + colorF.z +
                                   colorG.z + colorH.z + colorI.z) / 9.0;
                    }
                    else
                    {
                        ray.target.x = x - deltaP; ray.target.y =
                             y - deltaP; ray.target.z = 0.0;
                        rtPoint colorA = rayTracer.trace_ray(ray);

                        ray.target.x = x - deltaP; ray.target.y =
                             y + deltaP; ray.target.z = 0.0;
                        rtPoint colorB = rayTracer.trace_ray(ray);

                        ray.target.x = x + deltaP; ray.target.y =
                             y - deltaP; ray.target.z = 0.0;
                        rtPoint colorC = rayTracer.trace_ray(ray);

                        color.x = colorA.x;
                        color.y = colorA.y;
                        color.z = colorA.z;
                    }

                    Color colorpx = Color.FromArgb((int)color.x,
                        (int)color.y, (int)color.z);
                    newBitmap.SetPixel(i, j, colorpx);
                    iCounter++;
                    Monitor.Enter(form1);

                    form1.CallBack(4, iCounter);

                    Monitor.Exit(form1);
                }
            }
            newBitmap.Save(Application.StartupPath+"\\oneshot.bmp");

            Monitor.Enter(form1);

            form1.CallBack(2, 0);

            Monitor.Exit(form1);

        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
CEO
Brazil Brazil
"A well written code is self explanatory" - Anonymous Programmer
"The number of meetings is directly proportional to the bad management" - Another Anonymous Programmer
Founder @TIHUNTER.COM.BR
Linkedin Profile

Comments and Discussions