Skip to content

Commit

Permalink
Fixes to quanta
Browse files Browse the repository at this point in the history
  • Loading branch information
z-adams committed Feb 15, 2021
1 parent e4c32ac commit d8c1393
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 63 deletions.
28 changes: 0 additions & 28 deletions src/adera/ShipResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,6 @@ using namespace osp;
using namespace osp::active;
using namespace adera::active::machines;

/* ShipResourceType */

double ShipResourceType::resource_volume(uint64_t quantity) const
{
double units = static_cast<double>(quantity) / std::pow(2.0, m_quanta);
return units * m_volume;
}

double ShipResourceType::resource_mass(uint64_t quantity) const
{
double units = static_cast<double>(quantity) / std::pow(2.0, m_quanta);
return units * m_mass;
}

uint64_t ShipResourceType::resource_capacity(double volume) const
{
double units = volume / m_volume;
double quantaPerUnit = std::pow(2.0, m_quanta);
return static_cast<uint64_t>(units * quantaPerUnit);
}

uint64_t ShipResourceType::resource_quantity(double mass) const
{
double units = mass / m_mass;
double quantaPerUnit = std::pow(2.0, m_quanta);
return static_cast<uint64_t>(units * quantaPerUnit);
}

/* MachineContainer */

void MachineContainer::propagate_output(WireOutput* output)
Expand Down
90 changes: 62 additions & 28 deletions src/adera/ShipResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
*/
#pragma once
#include <string>
#include <assert.h>

#include "osp/Resource/Resource.h"
#include "osp/Active/SysMachine.h"
#include "osp/CommonMath.h"
#include "osp/CommonPhysics.h"

namespace adera::active::machines
Expand All @@ -41,24 +43,28 @@ namespace adera::active::machines
* the available precision to avoid infinite-fuel exploits.
* The 64-bit range is divided into two sections by an arbitrary choice of unit.
*
* A resource is specified by a volume, a mass, and a "quanta" value. The
* "quanta" value specifies the number of bits that represents the volume
* of resource in the definition. This volume is divided into (2^quanta)
* pieces, making 1/(2^quanta) the smallest representable quantity of the
* resource. The remaining (64-quanta) bits of precision represent tank
* capacity.
*
* Example resource:
* identifier: lox
* name: Liquid Oxygen
* quanta: 16
* mass: 1141.0 (kg) (per 2^quanta)
* volume: 1.0 (m^3) (per 2^quanta)
*
* The smallest representable quantity is unit/(2^quanta), which in this case is:
* volume: (1.0 m^3)/(2^16) = 1.5e-5 m^3 (15.2 mL)
* or mass: (1141.0 kg)/(2^16) = 0.017 kg (17.4 g)
*
* quantaPerUnit: 2^16
* mass: 1141.0 (kg) (per quantaPerUnit)
* volume: 1.0 (m^3) (per quantaPerUnit)
*
* Terminology:
*
* UNIT - The quantity of resource used in its definition. For example, the
* above example defines one unit of Liquid Oxygen to contain 1 cubic meter of
* resource, which masses 1141.0 kilograms.
*
* QUANTA - The resource definition also contains a value which defines the
* number of "quanta per unit" (QPU). This value is a power of two which
* determines the smallest representable quantity of the resource. Given a QPU
* value of 2^16, 16 bits of precision will be used to divide one unit of
* resource into pieces. In the above exapmle, the smallest representable
* quantity of resource (1) thus represents 1/(2^16) = 1.526e-5 units, or
* 15.26ml of LOx. The remaining 48 bits of precision are free to represent
* tank capacity.
*
* A fuel tank with volume 10 m^3 would thus store 655360 units of LOx. With 16
* bits dedicated to the subdivision of 1.0 m^3 of LOx, the remaining 48 bits can
* represent a maximum fuel capacity up to 281474976710656 m^3 (321 Teratons) of
Expand All @@ -75,34 +81,62 @@ namespace adera::active::machines
struct ShipResourceType
{
// A short, unique, identifying name readable by both human and machine
std::string m_identifier;
const std::string m_identifier;

// The full, screen-display name of the resource
std::string m_displayName;
const std::string m_displayName;

// 1/(2^quanta) is the smallest representable quantity of this resource
uint8_t m_quanta;
// 1/(QPU) is the smallest representable quantity of this resource; must be a power of 2
const uint64_t m_quantaPerUnit;

// The mass (in kg) of 2^quanta units of this resource
float m_mass;
// The volume (in m^3) of one unit of this resource
const float m_volume;

// The volume (in m^3) of 2^quanta units of this resource
float m_volume;
// The mass (in kg) of 1 unit of this resource
const float m_mass;

// The density of this resource (kg/m^3)
float m_density;
const float m_density;

// Compute the volume of the specified quantity of resource
double resource_volume(uint64_t quantity) const;
constexpr double resource_volume(uint64_t quantity) const
{
double units = static_cast<double>(quantity) / m_quantaPerUnit;
return units * m_volume;
}

// Compute the mass of the specified quantity of resource
double resource_mass(uint64_t quantity) const;
constexpr double resource_mass(uint64_t quantity) const
{
double units = static_cast<double>(quantity) / m_quantaPerUnit;
return units * m_mass;
}

// Compute the quantity of resource that fits in the specified volume
uint64_t resource_capacity(double volume) const;
constexpr uint64_t resource_capacity(double volume) const
{
double units = volume / m_volume;
return static_cast<uint64_t>(units * m_quantaPerUnit);
}

// Compute the quantity of resource that masses the specified amount
uint64_t resource_quantity(double mass) const;
constexpr uint64_t resource_quantity(double mass) const
{
double units = mass / m_mass;
return static_cast<uint64_t>(units * m_quantaPerUnit);
}

ShipResourceType(std::string identifier, std::string displayName,
uint64_t quantaPerUnit, float volume, float mass, float density)
: m_identifier(std::move(identifier))
, m_displayName(std::move(displayName))
, m_quantaPerUnit(quantaPerUnit)
, m_volume(volume)
, m_mass(mass)
, m_density(density)
{
assert(osp::math::is_power_of_2(m_quantaPerUnit));
}
};

struct ShipResource
Expand Down
48 changes: 48 additions & 0 deletions src/osp/CommonMath.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Open Space Program
* Copyright © 2019-2020 Open Space Program Project
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once

#include "types.h"
#include <type_traits>

namespace osp::math
{

template <typename UINT_T>
constexpr UINT_T uint_2pow(UINT_T exponent)
{
static_assert(std::is_integral<UINT_T>::value, "Unsigned int required");
return UINT_T(1) << exponent;
}

template <typename UINT_T>
constexpr bool is_power_of_2(UINT_T value)
{
static_assert(std::is_integral<UINT_T>::value, "Unsigned int required");
// Test to see if the value contains more than 1 set bit
return !(value == 0) && !(value & (value - 1));
}

} // namespace osp::math
16 changes: 9 additions & 7 deletions src/test_application/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,15 @@ void load_a_bunch_of_stuff()

// Load placeholder fuel type
using adera::active::machines::ShipResourceType;
ShipResourceType fuel;
fuel.m_identifier = "fuel";
fuel.m_displayName = "Rocket fuel";
fuel.m_quanta = 16;
fuel.m_mass = 1.0f;
fuel.m_volume = 0.001f;
fuel.m_density = fuel.m_mass / fuel.m_volume;
ShipResourceType fuel
{
"fuel", // identifier
"Rocket fuel", // display name
1 << 16, // quanta per unit
1.0f, // volume per unit (m^3)
1000.0f, // mass per unit (kg)
1000.0f // density (kg/m^3)
};

lazyDebugPack.add<ShipResourceType>("fuel", std::move(fuel));

Expand Down

0 comments on commit d8c1393

Please sign in to comment.