File: JOYAxes3D.m

package info (click to toggle)
sameboy 1.0.2%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 10,632 kB
  • sloc: ansic: 29,954; objc: 22,249; asm: 1,424; pascal: 1,373; makefile: 1,064; xml: 111
file content (129 lines) | stat: -rw-r--r-- 3,417 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
#import "JOYAxes3D.h"
#import "JOYElement.h"

@interface JOYAxes3D()
@property unsigned rotation; // in 90 degrees units, clockwise
@end

@implementation JOYAxes3D
{
    JOYElement *_element1, *_element2, *_element3;
    double _state1, _state2, _state3;
    int32_t _minX, _minY, _minZ;
    int32_t _maxX, _maxY, _maxZ;
    double _gApproximation;
}

+ (NSString *)usageToString: (JOYAxes3DUsage) usage
{
    if (usage < JOYAxes3DUsageNonGenericMax) {
        return inline_const(NSString *[], {
            @"None",
            @"Acceleretion",
            @"Orientation",
            @"Gyroscope",
        })[usage];
    }
    if (usage >= JOYAxes3DUsageGeneric0) {
        return [NSString stringWithFormat:@"Generic 3D Analog Control %d", usage - JOYAxes3DUsageGeneric0];
    }
    
    return [NSString stringWithFormat:@"Unknown Usage 3D Axes %d", usage];
}

- (NSString *)usageString
{
    return [self.class usageToString:_usage];
}

- (uint64_t)uniqueID
{
    return _element1.uniqueID | (uint64_t)self.combinedIndex << 32;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<%@: %p, %@ (%llx); State: (%.2f, %.2f, %.2f)>", self.className, self, self.usageString, self.uniqueID, _state1, _state2, _state3];
}

- (instancetype)initWithFirstElement:(JOYElement *)element1 secondElement:(JOYElement *)element2 thirdElement:(JOYElement *)element3
{
    self = [super init];
    if (!self) return self;
    
    _element1 = element1;
    _element2 = element2;
    _element3 = element3;

    _maxX = element1? element1.max :  1;
    _maxY = element2? element2.max :  1;
    _maxZ = element3? element3.max :  1;
    _minX = element1? element1.min : -1;
    _minY = element2? element2.min : -1;
    _minZ = element3? element3.min : -1;
    
    return self;
}

- (JOYPoint3D)rawValue
{
    return (JOYPoint3D){_state1, _state2, _state3};
}

- (JOYPoint3D)normalizedValue
{
    double distance = sqrt(_state1 * _state1 + _state2 * _state2 + _state3 * _state3);
    if (distance == 0) {
        distance = 1;
    }
    return (JOYPoint3D){_state1 / distance, _state2 / distance, _state3 / distance};
}

- (JOYPoint3D)gUnitsValue
{
    double distance = _gApproximation ?: 1;
    return (JOYPoint3D){_state1 / distance, _state2 / distance, _state3 / distance};
}

- (bool)updateState
{
    int32_t x = [_element1 value];
    int32_t y = [_element2 value];
    int32_t z = [_element3 value];

    if (x == 0 && y == 0 && z == 0) return false;
    
    double old1 = _state1, old2 = _state2, old3 = _state3;
    _state1 = (x - _minX) / (double)(_maxX - _minX) * 2 - 1;
    _state2 = (y - _minY) / (double)(_maxY - _minY) * 2 - 1;
    _state3 = (z - _minZ) / (double)(_maxZ - _minZ) * 2 - 1;
    
    double distance = sqrt(_state1 * _state1 + _state2 * _state2 + _state3 * _state3);
    if (_gApproximation == 0) {
        _gApproximation = distance;
    }
    else {
        _gApproximation = _gApproximation * 0.9999 + distance * 0.0001;
    }
    
    double temp = _state1;
    switch (_rotation & 3) {
        case 0: break;
        case 1:
            _state1 = -_state3;
            _state3 = temp;
            break;
        case 2:
            _state1 = -_state1;
            _state3 = -_state3;
            break;
        case 3:
            _state1 = _state3;
            _state3 = -temp;
            break;
    }

    return old1 != _state1 || old2 != _state2 || old3 != _state3;
}

@end