/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
//
// Filename: encodertypeentry.cpp
// Project: wwbitpack.lib
// Author: Tom Spencer-Smith
// Date: June 2000
// Description:
//
//-----------------------------------------------------------------------------
#include "encodertypeentry.h" // I WANNA BE FIRST!
#include
#include
#include "wwdebug.h"
#include "miscutil.h"
#include "mathutil.h"
static const int MAX_BITS = 32;
//-----------------------------------------------------------------------------
cEncoderTypeEntry::cEncoderTypeEntry()
{
Invalidate();
}
//-----------------------------------------------------------------------------
bool cEncoderTypeEntry::Is_Valid() const
{
return
((Max - Min > -MISCUTIL_EPSILON) &&
(Resolution > -MISCUTIL_EPSILON) &&
(BitPrecision >= 0));
}
//-----------------------------------------------------------------------------
void cEncoderTypeEntry::Invalidate()
{
Min = 1;
Max = -1;
Resolution = -1;
BitPrecision = 0;
}
//-----------------------------------------------------------------------------
bool cEncoderTypeEntry::Is_Value_In_Range(double value) const
{
return (value >= Min - MISCUTIL_EPSILON && value <= Max + MISCUTIL_EPSILON);
}
//-----------------------------------------------------------------------------
void cEncoderTypeEntry::Init(double min, double max, double resolution)
{
WWASSERT(!Is_Valid());
WWASSERT(max - min > -MISCUTIL_EPSILON);
WWASSERT(resolution > MISCUTIL_EPSILON);
Min = min;
Max = max;
Calc_Bit_Precision(resolution);
WWASSERT(Is_Valid());
}
//-----------------------------------------------------------------------------
void cEncoderTypeEntry::Init(int num_bits)
{
WWASSERT(!Is_Valid());
WWASSERT(num_bits > 0 && num_bits <= 32);
Min = 0;
BitPrecision = num_bits;
Resolution = 1;
UINT max = 0;
for (int i = 0; i < num_bits; i++) {
max += 1 << i;
}
Max = max;
WWASSERT(Is_Valid());
}
//-----------------------------------------------------------------------------
bool cEncoderTypeEntry::Scale(double value, ULONG & scaled_value)
{
WWASSERT(Is_Valid());
bool is_in_range = Is_Value_In_Range(value);
if (!is_in_range) {
value = Clamp(value);
}
scaled_value = static_cast
(cMathUtil::Round((value - Min) / Resolution));
return is_in_range;
}
//-----------------------------------------------------------------------------
double cEncoderTypeEntry::Unscale(ULONG u_value)
{
WWASSERT(Is_Valid());
double value = Min + u_value * Resolution;
WWASSERT(Is_Value_In_Range(value));
return value;
}
//-----------------------------------------------------------------------------
double cEncoderTypeEntry::Clamp(double value)
{
WWASSERT(Is_Valid());
double retval = value;
if (retval < Min) {
retval = Min;
} else if (retval > Max) {
retval = Max;
}
return retval;
}
//-----------------------------------------------------------------------------
void cEncoderTypeEntry::Calc_Bit_Precision(double resolution)
{
//
// Calculate the minimum number of bits required to encode this type with
// the specified resolution.
//
WWASSERT(Max - Min > -MISCUTIL_EPSILON);
WWASSERT(resolution > MISCUTIL_EPSILON);
double f_units = (double) ceil((Max - Min) / resolution - MISCUTIL_EPSILON) + 1;
WWASSERT(f_units <= UINT_MAX + MISCUTIL_EPSILON);
UINT units = (UINT) f_units;
BitPrecision = 0;
UINT max_units = 0;
while (max_units < units) {
max_units += 1 << BitPrecision;
BitPrecision++;
if (BitPrecision == 1) {
max_units++;
}
}
WWASSERT(BitPrecision > 0 && BitPrecision <= MAX_BITS);
WWASSERT(max_units > 0);
Resolution = (Max - Min) / (double) (max_units - 1);
/*TSS2001
if (Resolution > 0) {
WWASSERT(max_units ==
(UINT) ceil((Max - Min) / Resolution - MISCUTIL_EPSILON) + 1);
}
*/
}