File: PxDeepUtils.cpp

package info (click to toggle)
openexr 3.1.13-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 37,616 kB
  • sloc: cpp: 186,653; ansic: 24,266; sh: 173; python: 68; makefile: 23
file content (143 lines) | stat: -rw-r--r-- 3,744 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) Contributors to the OpenEXR Project.
//

#include "PxDeepUtils.h"

namespace PxDeep {

//-*****************************************************************************
// Density/Viz/DZ calculations are always performed in double precision.
// We try to leave them alone as much as possible, but the logarithm can get
// weird for very very small numbers. The "isfinite" call basically rules
// out NaN and Infinity results, though it doesn't bother with subnormal
// numbers, since the error case we're worried about is log being too big.
// viz = exp( -dz * density )
// log( viz ) = -dz * density
// density = -log( viz ) / dz
double DensityFromVizDz( double i_viz, double i_dz )
{
    assert( i_viz >= 0.0 );
    assert( i_viz <= 1.0 );
    assert( i_dz >= 0.0 );

    if ( i_viz >= 1.0 )
    {
        // There's no attenuation at all, so there's no density!
        return 0.0;
    }
    else if ( i_viz <= 0.0 )
    {
        // There's total attenuation, so we use our max density.
        return PXDU_DENSITY_OF_VIZ_0;
    }
    else if ( i_dz <= 0.0 )
    {
        // There's no depth, and viz is greater than zero,
        // so we assume the density is as high as possible
        return PXDU_DENSITY_OF_VIZ_0;
    }
    else
    {
        double d = -log( i_viz ) / i_dz;
        if ( !isfinite( d ) )
        {
            return PXDU_DENSITY_OF_VIZ_0;
        }
        else
        {
            return d;
        }
    }
}

//-*****************************************************************************
// We can often treat "density times dz" as a single quantity without
// separating it.
// viz = exp( -densityTimesDz )
// log( viz ) = -densityTimesDz
// densityTimesDz = -log( viz )
double DensityTimesDzFromViz( double i_viz )
{
    assert( i_viz >= 0.0 );
    assert( i_viz <= 1.0 );

    if ( i_viz >= 1.0 )
    {
        // There's no attenuation at all, so there's no density!
        return 0.0;
    }
    else if ( i_viz <= 0.0 )
    {
        // There's total attenuation, so we use our max density.
        return PXDU_DENSITY_OF_VIZ_0 * PXDU_DZ_OF_VIZ_0;
    }
    else
    {
        double d = -log( i_viz );
        if ( !isfinite( d ) )
        {
            return PXDU_DENSITY_OF_VIZ_0 * PXDU_DZ_OF_VIZ_0;
        }
        else
        {
            return d;
        }
    }
}

//-*****************************************************************************
// viz = exp( -dz * density )
// log( viz ) = -dz * density
// dz = -log( viz ) / density
// Note that this is basically the same as the computation above.
double DzFromVizDensity( double i_viz, double i_density )
{
    assert( i_viz >= 0.0 );
    assert( i_viz <= 1.0 );
    assert( i_density >= 0.0 );

    if ( i_viz >= 1.0 )
    {
        // There's no attenuation, so there's no depth.
        return 0.0;
    }
    else if ( i_viz <= 0.0 )
    {
        // There's total attenuation, so we use the smallest depth
        // for our max density.
        return PXDU_DZ_OF_VIZ_0;
    }
    else if ( i_density <= 0.0 )
    {
        // Hmmm. There's no density, but there is some attenuation,
        // which basically implies an infinite depth.
        // We'll use the minimum density.
        // This whole part is hacky at best.
        double dz = -log( i_viz ) / PXDU_MIN_NON_ZERO_DENSITY;
        if ( !isfinite( dz ) )
        {
            return PXDU_MAX_DZ;
        }
        else
        {
            return dz;
        }
    }
    else
    {
        double dz = -log( i_viz ) / i_density;
        if ( !isfinite( dz ) )
        {
            return PXDU_MAX_DZ;
        }
        else
        {
            return dz;
        }
    }
}

} // End namespace PxDeep