Coder Social home page Coder Social logo

ray-tracer-challenge-netcore's Introduction

Hi there ๐Ÿ‘‹

ray-tracer-challenge-netcore's People

Contributors

simonech avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ray-tracer-challenge-netcore's Issues

Exercise 1

Hey,

With your Projectile's velocity, I believe it should be normalised "Tuple.Vector(1, 1, 0).Normalise()"

P.S Thanks for kicking off this - I've got the book and I'm following along!

Suggestions for coding conventions

The way the code is written might be your preferences and therefore I did not submit a pull request.

  1. Namespace - suggest camel case instead of codeclimber.raytracer use CodeClimber.RayTracer
  2. There is a mix of code using this. and other parts of code not using this., particularly in Tuple.cs
  3. Suggest implementing IEquatable<T> and also implement override bool Equals(object obj) with override int GetHashCode(). This is new for me, so the idea of the suggestion is sound but the implementation might be questionable. At first I was wondering why even have this and the reason is to assume equality for doubles with a particular precision, 4.000001 equals 4.000002 are equal. Performance it part of this hence the duplication of the testing for equality. In examples I have see the equality test is in both override bool Equals(object obj) and bool Equals(T other) instead of having override bool Equals(object obj) call bool Equals(T other) after unboxing. But what is a few milliseconds. See below for implementation.
  4. Add a test where values are different yet are equal. Either indirectly with a Tuple having values Tuple(4.3, -4.000001, 3.1, 0) and Tuple(4.3, -4.000002, 3.1, 0) or testing the extension method.
public override int GetHashCode()
{
    return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
}

public override bool Equals(object obj)
{
    Tuple other = obj as Tuple;
    if (other == null)
    {
        return false;
    }

    return (other.X.EqualsD(X)
        && other.Y.EqualsD(Y)
        && other.Z.EqualsD(Z)
        && other.W.EqualsD(W));
}

public bool Equals(Tuple other)
{
    if (other == null)
    {
        return false;
    }

    return (other.X.EqualsD(X)
        && other.Y.EqualsD(Y)
        && other.Z.EqualsD(Z)
        && other.W.EqualsD(W));
}

Suggestion: Concrete types for Vector and Point

RE: Concrete Tuple Types

I got the book!

In one of the first post you reason about concrete classes for vector and point. I think I have some suggestions. You can review my code referenced above.

After getting into Chapter 6 and having Tuple types throughout the code and not knowing if the property or variable is a Point or a Vector I decided to look into making concrete types.

I was able to build the concrete types Tuple, Vector, and Point, it appears to be a lot of duplicate code, but the code that is duplicated are "one liners" of code. Mainly the operator methods, returning their respective type after doing an operation instead of Tuple with the W set to 0 or 1 to designate a vector or point.

I had built four classes, a RtBaseTuple which the other three are derived from, RtTuple, RtVector, and RtPoint. The base class has all the properties along with the operations, Dot, Magnitude, that return the same type regardless of the derived type. The derived classes have methods in them that will return their specific type after doing *, /, +, Normalized, Cross, etc.

I believe the author did not want to complicate things with multiple things. Also by way of using some magic was able to have a Vector created from a Point by doing math. I removed some of the magic by implying the rules instead of having them inferred. If you subtract a point from a point return a vector instead of tuple that is a vector because the W went to 0 after subtracting 1 from 1.

In my RtPoint class I have this, subtract two points and return a vector.

static public RtVector operator -(RtPoint left, RtPoint right)
    => new RtVector(left.X - right.X, left.Y - right.Y, left.Z - right.Z);

I think the biggest challenge and reason for duplicate code for a derived type is not being able to return a different type. There is no way to have a class Tuple with a virtual Negate or Normalized that you can override with a different return type . In the derived class Vector you can't override Normalized and return Vector, it is expecting Tuple to be returned. Something about co-variance. But even if you did have something like this you would still end up with duplicate code or code wrapping other code.

I think the thing that hit me was the author eluding to having Color be like a tuple and reuse the code, but there was no way of doing that and if you did you still end up with duplicate code trying to wrap X around Red, Y around Green and Z around Blue, and ignoring the W property. Hence why there is a class just for color. Also in part of the book there is math that breaks the magic, after the operation is done you have to reset the W value.

This hacking was a testament to having a boat load of tests. After screwing around and getting everything to pass the test, my exercises still worked as they should.

Replace naive primitives with System.Numerics classes

System.Numerics provides Vector3 and Vector4 structures, as well as Matrixes, and all the possible operations.
Those classes are also optimized to use SIMD operations in the CPU.

After the actual exercise of the book is complete, it might be a good idea to try and replace the primitives implemented from scratch in chapters 1-4 with these purpose mades classes

Suggestion for possible enhancements

Hi @simonech

Good to see someone else doing the ray tracer challenge with .NET CORE!

I have some suggestions if you don't mind :)

  1. Instead of creating a method called add, you can define an operator called + (same for -, /, *) like this:
public static Tupple operator +(Tupple left, Tupple right)  
{  
    return new Tupple(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);  
}

usage:

var t1 = new Tupple(1.0f, 1.0f, 1.0f, 1.0f);
var t2 = new Tupple(2.0f, 2.0f, 2.0f, 2.0f);
var sum = t1 + t2;
  1. I am not sure which version of .NET CORE you're using, but since 2.1 preview it has included a math library for float values

system.mathf

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.