Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/openal-0.0.8/src/al_distance.c @ 17

Last change on this file since 17 was 17, checked in by landauf, 16 years ago

added openal

File size: 4.3 KB
Line 
1/* -*- mode: C; tab-width:8; c-basic-offset:8 -*-
2 * vi:set ts=8:
3 *
4 * al_distance.c
5 *
6 * Implementation of distance models.
7 */
8#include "al_siteconfig.h"
9
10#include <math.h>
11
12#include "al_distance.h"
13#include "al_main.h"
14
15/*
16 * No distance attenuation.  Which means we return 1.0 for all values.
17 */
18static ALfloat
19noAttenuation( UNUSED(ALfloat distance),
20               UNUSED(ALfloat rolloffFactor),
21               UNUSED(ALfloat referenceDistance),
22               UNUSED(ALfloat maxDistance))
23{
24        return 1.0f;
25}
26
27static ALfloat
28inverseDistance( ALfloat distance,
29                 ALfloat rolloffFactor,
30                 ALfloat referenceDistance,
31                 UNUSED(ALfloat maxDistance))
32{
33        /*
34         * At this distance, the gain formula has a singularity and smaller
35         * distances would result in a negative gain. In these cases, the spec
36         * explicitly requires "no attenuation".
37         */
38        ALfloat critDist = referenceDistance + (rolloffFactor * (distance - referenceDistance));
39        if (critDist <= 0.0f) {
40                return 1.0f;
41        }
42
43        return referenceDistance / critDist;
44}
45
46static ALfloat
47inverseDistanceClamped( ALfloat distance,
48                        ALfloat rolloffFactor,
49                        ALfloat referenceDistance,
50                        ALfloat maxDistance )
51{
52        ALfloat critDist;
53
54        if (maxDistance <= referenceDistance) {
55                return 1.0;
56        }
57
58        /* distance = MAX( distance, referenceDistance ) */
59        if( distance < referenceDistance ) {
60                distance = referenceDistance;
61        }
62
63        /* distance = MIN( distance, maxDistance ) */
64        if( distance > maxDistance ) {
65                distance = maxDistance;
66        }
67
68        /*
69         * At this distance, the gain formula has a singularity and smaller
70         * distances would result in a negative gain. In these cases, the spec
71         * explicitly requires "no attenuation".
72         */
73        critDist = referenceDistance + (rolloffFactor * (distance - referenceDistance));
74        if (critDist <= 0.0f) {
75                return 1.0f;
76        }
77
78        return referenceDistance / critDist;
79}
80
81static ALfloat
82linearDistance( ALfloat distance,
83                ALfloat rolloffFactor,
84                ALfloat referenceDistance,
85                ALfloat maxDistance)
86{
87        if (maxDistance <= referenceDistance) {
88                return 1.0f;
89        }
90
91        return 1.0f - rolloffFactor * (distance - referenceDistance) / (maxDistance - referenceDistance);
92}
93
94static ALfloat
95linearDistanceClamped( ALfloat distance,
96                       ALfloat rolloffFactor,
97                       ALfloat referenceDistance,
98                       ALfloat maxDistance)
99{
100        if (maxDistance <= referenceDistance) {
101                return 1.0f;
102        }
103
104        /* distance = MAX( distance, referenceDistance ) */
105        if( distance < referenceDistance ) {
106                distance = referenceDistance;
107        }
108
109        /* distance = MIN( distance, maxDistance ) */
110        if( distance > maxDistance ) {
111                distance = maxDistance;
112        }
113
114        return 1.0f - rolloffFactor * (distance - referenceDistance) / (maxDistance - referenceDistance);
115}
116
117static ALfloat
118exponentDistance( ALfloat distance,
119                  ALfloat rolloffFactor,
120                  ALfloat referenceDistance,
121                  UNUSED(ALfloat maxDistance))
122{
123        ALfloat quotient;
124
125        if (referenceDistance == 0.0f) {
126                return 1.0f;
127        }
128
129        quotient = distance / referenceDistance;
130        if (quotient == 0.0f) {
131                return 1.0f;
132        }
133
134        return (ALfloat)pow(quotient, -rolloffFactor);
135}
136
137static ALfloat
138exponentDistanceClamped( ALfloat distance,
139                         ALfloat rolloffFactor,
140                         ALfloat referenceDistance,
141                         ALfloat maxDistance)
142{
143        ALfloat quotient;
144
145        if ((maxDistance <= referenceDistance) || (referenceDistance == 0.0f)) {
146                return 1.0f;
147        }
148
149        /* distance = MAX( distance, referenceDistance ) */
150        if( distance < referenceDistance ) {
151                distance = referenceDistance;
152        }
153
154        /* distance = MIN( distance, maxDistance ) */
155        if( distance > maxDistance ) {
156                distance = maxDistance;
157        }
158
159        quotient = distance / referenceDistance;
160        if (quotient == 0.0f) {
161                return 1.0f;
162        }
163
164        return (ALfloat)pow(quotient, -rolloffFactor);
165}
166
167void
168_alUpdateDistanceModel( AL_context *cc )
169{
170        switch( cc->distance_model) {
171        case AL_NONE:
172                cc->distance_func = noAttenuation;
173                break;
174        case AL_INVERSE_DISTANCE:
175                cc->distance_func = inverseDistance;
176                break;
177        case AL_INVERSE_DISTANCE_CLAMPED:
178                cc->distance_func = inverseDistanceClamped;
179                break;
180        case AL_LINEAR_DISTANCE:
181                cc->distance_func = linearDistance;
182                break;
183        case AL_LINEAR_DISTANCE_CLAMPED:
184                cc->distance_func = linearDistanceClamped;
185                break;
186        case AL_EXPONENT_DISTANCE:
187                cc->distance_func = exponentDistance;
188                break;
189        case AL_EXPONENT_DISTANCE_CLAMPED:
190                cc->distance_func = exponentDistanceClamped;
191                break;
192        default:
193                /* should never happen, just to be safe */
194                cc->distance_func = inverseDistanceClamped;
195                break;
196        }
197}
Note: See TracBrowser for help on using the repository browser.