Skip to content

Commit

Permalink
uv_mapping for cylinder, cone, lemon and disc.
Browse files Browse the repository at this point in the history
Control by user with "uv_mapping direction", default +x
direction should avoid being colinear with axis/normal
  • Loading branch information
LeForgeron committed Sep 3, 2018
1 parent f09a7b4 commit 83a269c
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 40 deletions.
25 changes: 19 additions & 6 deletions source/core/shape/cone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,8 @@ Cone::Cone() : ObjectBase(CONE_OBJECT)
{
apex = Vector3d(0.0, 0.0, 1.0);
base = Vector3d(0.0, 0.0, 0.0);
uref = Vector3d(1.0, 0.0, 0.0);
vInverted = false;

apex_radius = 1.0;
base_radius = 0.0;
Expand Down Expand Up @@ -770,6 +772,7 @@ void Cone::Compute_Cone_Data()
base_radius = apex_radius;
apex_radius = tmpf;
axis.invert();
vInverted =~vInverted;
}
/* apex & base are different, yet, it might looks like a cylinder */
tmpf = base_radius * len / (apex_radius - base_radius);
Expand Down Expand Up @@ -927,7 +930,6 @@ void Cone::Compute_BBox()



#ifdef POV_ENABLE_CONE_UV

/*****************************************************************************
*
Expand Down Expand Up @@ -990,8 +992,17 @@ void Cone::UVCoord(Vector2d& Result, const Intersection *Inter, TraceThreadData
void Cone::CalcUV(const Vector3d& IPoint, Vector2d& Result) const
{
DBL len, x, y;
DBL phi, theta;
DBL phi, theta, thetaref;
Vector3d P;
Vector3d D, Axis;

// compute u origin vector as cross(cross( axis, uref), axis), with axis = apex-base
Axis = apex-base;
D = cross( cross( Axis, uref), Axis );
thetaref = atan2( D[Y], D[X] );
// Transform the point into the lemon space.
MInvTransPoint(P, IPoint, Trans);


// Transform the ray into the cone space.
MInvTransPoint(P, IPoint, Trans);
Expand Down Expand Up @@ -1042,17 +1053,19 @@ void Cone::CalcUV(const Vector3d& IPoint, Vector2d& Result) const
theta = TWO_M_PI - theta;
}

theta /= TWO_M_PI; // This will be from 0 to 1
theta -= thetaref;
theta += 2.0*TWO_M_PI;// to be positive
theta /= TWO_M_PI;
theta -= int(theta);
}
else
// This point is at one of the poles. Any value of xcoord will be ok...
theta = 0;

Result[U] = theta;
Result[V] = phi;
Result[U] = vInverted?(1-0-theta):theta;
Result[V] = vInverted?(1.0-phi):phi;

}

#endif // POV_ENABLE_CONE_UV

}
10 changes: 2 additions & 8 deletions source/core/shape/cone.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class Cone : public ObjectBase
DBL apex_radius; ///< Radius of the cone at the top.
DBL base_radius; ///< Radius of the cone at the bottom.
DBL dist; ///< Distance to end of cone in canonical coords.
Vector3d uref; ///< direction for origin of u in uv_mapping
bool vInverted;///< the v of uv-mapping is inverted

Cone();
virtual ~Cone();
Expand All @@ -86,13 +88,7 @@ class Cone : public ObjectBase
virtual bool All_Intersections(const Ray&, IStack&, TraceThreadData *);
virtual bool Inside(const Vector3d&, TraceThreadData *) const;
virtual void Normal(Vector3d&, Intersection *, TraceThreadData *) const;
#ifdef POV_ENABLE_CONE_UV
/// @attention
/// UV mapping of this primitive should not be enabled until the primary
/// parameterization has been amended so that users have full control over the
/// primitive's orientation, rather than just the axis of rotational symmetry.
virtual void UVCoord(Vector2d&, const Intersection *, TraceThreadData *) const;
#endif // POV_ENABLE_CONE_UV
virtual void Translate(const Vector3d&, const TRANSFORM *);
virtual void Rotate(const Vector3d&, const TRANSFORM *);
virtual void Scale(const Vector3d&, const TRANSFORM *);
Expand All @@ -103,9 +99,7 @@ class Cone : public ObjectBase
void Compute_Cylinder_Data();
protected:
int Intersect(const BasicRay& ray, CONE_INT *Intersection, TraceThreadData *Thread) const;
#ifdef POV_ENABLE_CONE_UV
void CalcUV(const Vector3d& IPoint, Vector2d& Result) const;
#endif // POV_ENABLE_CONE_UV
};

/// @}
Expand Down
32 changes: 28 additions & 4 deletions source/core/shape/disc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,21 @@ const DBL DEPTH_TOLERANCE = 1.0e-6;
bool Disc::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
int Intersection_Found;
Vector2d uv;
DBL Depth;
Vector3d IPoint;

Intersection_Found = false;

Thread->Stats()[Ray_Disc_Tests]++;
if (Intersect(ray, &Depth))
if (Intersect(ray, &Depth, uv[0], uv[1]))
{
Thread->Stats()[Ray_Disc_Tests_Succeeded]++;
IPoint = ray.Evaluate(Depth);

if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
{
Depth_Stack->push(Intersection(Depth,IPoint,this));
Depth_Stack->push(Intersection(Depth,IPoint, uv, this));
Intersection_Found = true;
}
}
Expand Down Expand Up @@ -129,9 +130,9 @@ bool Disc::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadDat
*
******************************************************************************/

bool Disc::Intersect(const BasicRay& ray, DBL *Depth) const
bool Disc::Intersect(const BasicRay& ray, DBL *Depth, DBL&u, DBL&v) const
{
DBL t, u, v, r2, len;
DBL t, r2, len;
Vector3d P, D;

/* Transform the point into the discs space */
Expand Down Expand Up @@ -426,6 +427,7 @@ Disc::Disc() : ObjectBase(DISC_OBJECT)
oradius2 = 1.0;

d = 0.0;
uref = Vector3d(1.0, 0.0, 0.0);

Trans = Create_Transform();

Expand Down Expand Up @@ -586,4 +588,26 @@ void Disc::Compute_BBox()
Recompute_BBox(&BBox, Trans);
}

void Disc::UVCoord(Vector2d& result, const Intersection *inter, TraceThreadData *) const
{
Vector2d uv( inter->Iuv);
Vector3d D;
DBL len;
DBL theta,thetaref;
// u = 0 for matching half-plane with normal and uref, then use normal for orientation
// Back to disc space
// compute u origin vector as cross( cross( n, uref), n)
D = cross ( cross( normal, uref), normal );
theta = atan2( uv[V], uv[U]);
thetaref = atan2( D[Y], D[X]);
theta -= thetaref;
theta += 2.0*TWO_M_PI;// to always be positive
theta /= TWO_M_PI;
result[U] = theta-int(theta);// from 0 to 1, never reaching 1
// v = 0 for iradius2, 1 for oradius2, and linear interpolation along that
len = Sqr(uv[U])+Sqr(uv[V]);
result[V] = (sqrt(len)-sqrt(iradius2))/(sqrt(oradius2)-sqrt(iradius2));

}

}
12 changes: 5 additions & 7 deletions source/core/shape/disc.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ class Disc : public ObjectBase
Vector3d center; ///< Center of the disc.
Vector3d normal; ///< Direction perpendicular to the disc (plane normal).
DBL d; ///< The constant part of the plane equation.
DBL iradius2; ///< Distance from center to inner circle of the disc.
DBL oradius2; ///< Distance from center to outer circle of the disc.
DBL iradius2; ///< squared Distance from center to inner circle of the disc.
DBL oradius2; ///< squared Distance from center to outer circle of the disc.
Vector3d uref; ///< direction for the origin of u in uvmapping

Disc();
virtual ~Disc();
Expand All @@ -79,10 +80,7 @@ class Disc : public ObjectBase
virtual bool All_Intersections(const Ray&, IStack&, TraceThreadData *);
virtual bool Inside(const Vector3d&, TraceThreadData *) const;
virtual void Normal(Vector3d&, Intersection *, TraceThreadData *) const;
// NOTE: UV mapping of this primitive should not be implemented without also amending
// the primary parameterization so that users have full control over the primitive's
// orientation, rather than just the normal vector.
// virtual void UVCoord(Vector2d&, const Intersection *, TraceThreadData *) const;
virtual void UVCoord(Vector2d&, const Intersection *, TraceThreadData *) const;
virtual void Translate(const Vector3d&, const TRANSFORM *);
virtual void Rotate(const Vector3d&, const TRANSFORM *);
virtual void Scale(const Vector3d&, const TRANSFORM *);
Expand All @@ -91,7 +89,7 @@ class Disc : public ObjectBase

void Compute_Disc();
protected:
bool Intersect(const BasicRay& ray, DBL *Depth) const;
bool Intersect(const BasicRay& ray, DBL *Depth, DBL&u, DBL&v) const;
};

/// @}
Expand Down
18 changes: 12 additions & 6 deletions source/core/shape/lemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ Lemon::Lemon() : ObjectBase(LEMON_OBJECT)
{
apex = Vector3d(0.0, 0.0, 1.0);
base = Vector3d(0.0, 0.0, 0.0);
uref = Vector3d(1.0, 0.0, 0.0);

apex_radius = 0.0;
base_radius = 0.0;
Expand Down Expand Up @@ -754,7 +755,6 @@ void Lemon::Compute_BBox()
}


#ifdef POV_ENABLE_LEMON_UV

/*****************************************************************************
*
Expand Down Expand Up @@ -811,10 +811,15 @@ void Lemon::UVCoord(Vector2d& Result, const Intersection *Inter, TraceThreadData
void Lemon::CalcUV(const Vector3d& IPoint, Vector2d& Result) const
{
DBL len, x, y, z;
DBL phi, theta;
DBL phi, theta, thetaref;
Vector3d P;
Vector3d D, Axis;

// Transform the ray into the lemon space.
// compute u origin vector as cross(cross( axis, uref), axis), with axis = apex-base
Axis = apex-base;
D = cross( cross( Axis, uref), Axis );
thetaref = atan2( D[Y], D[X] );
// Transform the point into the lemon space.
MInvTransPoint(P, IPoint, Trans);

// the center of UV coordinate is <0, 0, 1/2>
Expand Down Expand Up @@ -867,8 +872,10 @@ void Lemon::CalcUV(const Vector3d& IPoint, Vector2d& Result) const
if (y < 0.0)
theta = TWO_M_PI - theta;
}

theta /= TWO_M_PI; // This will be from 0 to 1
theta -= thetaref;
theta += 2.0*TWO_M_PI;// to be positive
theta /= TWO_M_PI;
theta -= int(theta);
}
else
// This point is at one of the poles. Any value of xcoord will be ok...
Expand All @@ -879,6 +886,5 @@ void Lemon::CalcUV(const Vector3d& IPoint, Vector2d& Result) const

}

#endif // POV_ENABLE_LEMON_UV

}
9 changes: 1 addition & 8 deletions source/core/shape/lemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,7 @@ class Lemon : public ObjectBase
virtual bool All_Intersections(const Ray&, IStack&, TraceThreadData *);
virtual bool Inside(const Vector3d&, TraceThreadData *) const;
virtual void Normal(Vector3d&, Intersection *, TraceThreadData *) const;
#ifdef POV_ENABLE_LEMON_UV
/// @attention
/// UV mapping of this primitive should not be enabled until the primary
/// parameterization has been amended so that users have full control over the
/// primitive's orientation, rather than just the axis of rotational symmetry.
virtual void UVCoord(Vector2d&, const Intersection *, TraceThreadData *) const;
#endif // POV_ENABLE_LEMON_UV
virtual void Translate(const Vector3d&, const TRANSFORM *);
virtual void Rotate(const Vector3d&, const TRANSFORM *);
virtual void Scale(const Vector3d&, const TRANSFORM *);
Expand All @@ -104,11 +98,10 @@ class Lemon : public ObjectBase
DBL inner_radius; /* Radius of the inner circle */
DBL HorizontalPosition; /* horizontal position of the center of the inner circle */
DBL VerticalPosition; /* vertical position of the center of the inner circle */
Vector3d uref; ///< direction for origin of u in uv_mapping
protected:
int Intersect(const Vector3d& P, const Vector3d& D, LEMON_INT *Intersection, TraceThreadData *Thread) const;
#ifdef POV_ENABLE_LEMON_UV
void CalcUV(const Vector3d& IPoint, Vector2d& Result) const;
#endif // POV_ENABLE_LEMON_UV
};

/// @}
Expand Down
2 changes: 1 addition & 1 deletion source/core/shape/ovus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ void Ovus::CalcUV(const Vector3d& IPoint, Vector2d& Result) const
theta = 0;

Result[U] = theta;
Result[V] = phi;
Result[V] = 1.0-phi;

}

Expand Down
40 changes: 40 additions & 0 deletions source/parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2373,6 +2373,16 @@ ObjectPtr Parser::Parse_Cone ()
END_CASE
END_EXPECT

EXPECT_ONE
CASE(UV_MAPPING_TOKEN)
Parse_Vector(Object->uref);
END_CASE

OTHERWISE
UNGET
END_CASE
END_EXPECT

/* Compute run-time values for the cone */
Object->Compute_Cone_Data();

Expand Down Expand Up @@ -2429,6 +2439,16 @@ ObjectPtr Parser::Parse_Cylinder ()
END_CASE
END_EXPECT

EXPECT_ONE
CASE(UV_MAPPING_TOKEN)
Parse_Vector(Object->uref);
END_CASE

OTHERWISE
UNGET
END_CASE
END_EXPECT

Object->Compute_Cylinder_Data();

Object->Compute_BBox();
Expand Down Expand Up @@ -2487,6 +2507,16 @@ ObjectPtr Parser::Parse_Disc ()
END_CASE
END_EXPECT

EXPECT_ONE
CASE(UV_MAPPING_TOKEN)
Parse_Vector(Object->uref);
END_CASE

OTHERWISE
UNGET
END_CASE
END_EXPECT

/* Calculate info needed for ray-disc intersections */
tmpf = dot(Object->center, Object->normal);
Object->d = -tmpf;
Expand Down Expand Up @@ -3203,6 +3233,16 @@ ObjectPtr Parser::Parse_Lemon ()
END_CASE
END_EXPECT

EXPECT_ONE
CASE(UV_MAPPING_TOKEN)
Parse_Vector(Object->uref);
END_CASE

OTHERWISE
UNGET
END_CASE
END_EXPECT

/* Compute run-time values for the lemon */
Object->Compute_Lemon_Data( messageFactory, Token.FileHandle, Token.Token_File_Pos, Token.Token_Col_No );

Expand Down

0 comments on commit 83a269c

Please sign in to comment.