kopia lustrzana https://github.com/jameshball/osci-render
Fix SVG parsing bugs, object parsing bugs, rotation precision errors
rodzic
2157b8a867
commit
398f3268f5
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <numbers>
|
||||||
|
|
||||||
|
class MathUtil {
|
||||||
|
public:
|
||||||
|
|
||||||
|
// from https://stackoverflow.com/questions/11980292/how-to-wrap-around-a-range
|
||||||
|
static inline double wrapAngle(double angle) {
|
||||||
|
double twoPi = 2.0 * std::numbers::pi;
|
||||||
|
return angle - twoPi * floor(angle / twoPi);
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,16 +1,14 @@
|
||||||
#include "EffectApplication.h"
|
#include "EffectApplication.h"
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
#include "../MathUtil.h"
|
||||||
|
|
||||||
void EffectApplication::resetPhase() {
|
void EffectApplication::resetPhase() {
|
||||||
phase = 0.0;
|
phase = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double EffectApplication::nextPhase(double frequency, double sampleRate) {
|
double EffectApplication::nextPhase(double frequency, double sampleRate) {
|
||||||
phase += frequency / sampleRate;
|
phase += 2 * std::numbers::pi * frequency / sampleRate;
|
||||||
|
phase = MathUtil::wrapAngle(phase);
|
||||||
|
|
||||||
if (phase > 1) {
|
return phase;
|
||||||
phase -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return phase * 2 * std::numbers::pi;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "PerspectiveEffect.h"
|
#include "PerspectiveEffect.h"
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
#include "../MathUtil.h"
|
||||||
|
|
||||||
PerspectiveEffect::PerspectiveEffect(int versionHint) : versionHint(versionHint) {
|
PerspectiveEffect::PerspectiveEffect(int versionHint) : versionHint(versionHint) {
|
||||||
fixedRotateX = new BooleanParameter("Perspective Fixed Rotate X", "perspectiveFixedRotateX", versionHint, false);
|
fixedRotateX = new BooleanParameter("Perspective Fixed Rotate X", "perspectiveFixedRotateX", versionHint, false);
|
||||||
|
@ -31,19 +32,9 @@ Vector2 PerspectiveEffect::apply(int index, Vector2 input, const std::vector<dou
|
||||||
baseRotateZ = values[5] * std::numbers::pi;
|
baseRotateZ = values[5] * std::numbers::pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRotateX += baseRotateX * rotateSpeed;
|
currentRotateX = MathUtil::wrapAngle(currentRotateX + baseRotateX * rotateSpeed);
|
||||||
currentRotateY += baseRotateY * rotateSpeed;
|
currentRotateY = MathUtil::wrapAngle(currentRotateY + baseRotateY * rotateSpeed);
|
||||||
currentRotateZ += baseRotateZ * rotateSpeed;
|
currentRotateZ = MathUtil::wrapAngle(currentRotateZ + baseRotateZ * rotateSpeed);
|
||||||
|
|
||||||
if (currentRotateX > std::numbers::pi * 8) {
|
|
||||||
currentRotateX -= std::numbers::pi * 8;
|
|
||||||
}
|
|
||||||
if (currentRotateY > std::numbers::pi * 8) {
|
|
||||||
currentRotateY -= std::numbers::pi * 8;
|
|
||||||
}
|
|
||||||
if (currentRotateZ > std::numbers::pi * 8) {
|
|
||||||
currentRotateZ -= std::numbers::pi * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto x = input.x;
|
auto x = input.x;
|
||||||
auto y = input.y;
|
auto y = input.y;
|
||||||
|
|
|
@ -28,7 +28,11 @@ private:
|
||||||
|
|
||||||
int versionHint;
|
int versionHint;
|
||||||
|
|
||||||
float linearSpeedToActualSpeed(float rotateSpeed) {
|
double linearSpeedToActualSpeed(double rotateSpeed) {
|
||||||
return (std::exp(3 * juce::jmin(10.0f, std::abs(rotateSpeed))) - 1) / 50000.0;
|
double actualSpeed = (std::exp(3 * std::min(10.0, std::abs(rotateSpeed))) - 1) / 50000;
|
||||||
}
|
if (rotateSpeed < 0) {
|
||||||
|
actualSpeed *= -1;
|
||||||
|
}
|
||||||
|
return actualSpeed;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,8 +12,10 @@ Graph::Graph(int n, list< pair<int, int> > & edges):
|
||||||
{
|
{
|
||||||
int u = (*it).first;
|
int u = (*it).first;
|
||||||
int v = (*it).second;
|
int v = (*it).second;
|
||||||
|
|
||||||
AddEdge(u, v);
|
if (v < n && u < n) {
|
||||||
|
AddEdge(u, v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "WorldObject.h"
|
#include "WorldObject.h"
|
||||||
#include "../chinese_postman/ChinesePostman.h"
|
#include "../chinese_postman/ChinesePostman.h"
|
||||||
#include "tiny_obj_loader.h"
|
#include "tiny_obj_loader.h"
|
||||||
|
#include "../MathUtil.h"
|
||||||
|
|
||||||
struct pair_hash {
|
struct pair_hash {
|
||||||
inline std::size_t operator()(const std::pair<int, int>& v) const {
|
inline std::size_t operator()(const std::pair<int, int>& v) const {
|
||||||
|
@ -238,9 +239,9 @@ void WorldObject::setRotationSpeed(double rotateSpeed) {
|
||||||
// called whenever a new frame is drawn, so that the object can update its
|
// called whenever a new frame is drawn, so that the object can update its
|
||||||
// rotation
|
// rotation
|
||||||
void WorldObject::nextFrame() {
|
void WorldObject::nextFrame() {
|
||||||
currentRotateX = currentRotateX + baseRotateX * rotateSpeed;
|
currentRotateX = MathUtil::wrapAngle(currentRotateX + baseRotateX * rotateSpeed);
|
||||||
currentRotateY = currentRotateY + baseRotateY * rotateSpeed;
|
currentRotateY = MathUtil::wrapAngle(currentRotateY + baseRotateY * rotateSpeed);
|
||||||
currentRotateZ = currentRotateZ + baseRotateZ * rotateSpeed;
|
currentRotateZ = MathUtil::wrapAngle(currentRotateZ + baseRotateZ * rotateSpeed);
|
||||||
rotateX = baseRotateX + currentRotateX;
|
rotateX = baseRotateX + currentRotateX;
|
||||||
rotateY = baseRotateY + currentRotateY;
|
rotateY = baseRotateY + currentRotateY;
|
||||||
rotateZ = baseRotateZ + currentRotateZ;
|
rotateZ = baseRotateZ + currentRotateZ;
|
||||||
|
|
|
@ -45,7 +45,7 @@ double Vector2::magnitude() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Shape> Vector2::clone() {
|
std::unique_ptr<Shape> Vector2::clone() {
|
||||||
return std::unique_ptr<Shape>();
|
return std::make_unique<Vector2>(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Vector2::type() {
|
std::string Vector2::type() {
|
||||||
|
|
|
@ -5,17 +5,26 @@
|
||||||
|
|
||||||
SvgParser::SvgParser(juce::String svgFile) {
|
SvgParser::SvgParser(juce::String svgFile) {
|
||||||
auto doc = juce::XmlDocument::parse(svgFile);
|
auto doc = juce::XmlDocument::parse(svgFile);
|
||||||
std::unique_ptr<juce::Drawable> svg = juce::Drawable::createFromSVG(*doc);
|
if (doc != nullptr) {
|
||||||
juce::DrawableComposite* composite = dynamic_cast<juce::DrawableComposite*>(svg.get());
|
std::unique_ptr<juce::Drawable> svg = juce::Drawable::createFromSVG(*doc);
|
||||||
auto contentArea = composite->getContentArea();
|
juce::DrawableComposite* composite = dynamic_cast<juce::DrawableComposite*>(svg.get());
|
||||||
auto path = svg->getOutlineAsPath();
|
if (composite != nullptr) {
|
||||||
// apply transform to path to get the content area in the bounds -1 to 1
|
auto contentArea = composite->getContentArea();
|
||||||
path.applyTransform(juce::AffineTransform::translation(-contentArea.getX(), -contentArea.getY()));
|
auto path = svg->getOutlineAsPath();
|
||||||
path.applyTransform(juce::AffineTransform::scale(2 / contentArea.getWidth(), 2 / contentArea.getHeight()));
|
// apply transform to path to get the content area in the bounds -1 to 1
|
||||||
path.applyTransform(juce::AffineTransform::translation(-1, -1));
|
path.applyTransform(juce::AffineTransform::translation(-contentArea.getX(), -contentArea.getY()));
|
||||||
|
path.applyTransform(juce::AffineTransform::scale(2 / contentArea.getWidth(), 2 / contentArea.getHeight()));
|
||||||
|
path.applyTransform(juce::AffineTransform::translation(-1, -1));
|
||||||
|
|
||||||
pathToShapes(path, shapes);
|
pathToShapes(path, shapes);
|
||||||
Shape::removeOutOfBounds(shapes);
|
Shape::removeOutOfBounds(shapes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw an X to indicate an error.
|
||||||
|
shapes.push_back(std::make_unique<Line>(-0.5, -0.5, 0.5, 0.5));
|
||||||
|
shapes.push_back(std::make_unique<Line>(-0.5, 0.5, 0.5, -0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
SvgParser::~SvgParser() {}
|
SvgParser::~SvgParser() {}
|
||||||
|
@ -69,4 +78,4 @@ std::vector<std::unique_ptr<Shape>> SvgParser::draw() {
|
||||||
tempShapes.push_back(shape->clone());
|
tempShapes.push_back(shape->clone());
|
||||||
}
|
}
|
||||||
return tempShapes;
|
return tempShapes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,6 +380,7 @@
|
||||||
<FILE id="GKBQ8j" name="MainComponent.cpp" compile="1" resource="0"
|
<FILE id="GKBQ8j" name="MainComponent.cpp" compile="1" resource="0"
|
||||||
file="Source/MainComponent.cpp"/>
|
file="Source/MainComponent.cpp"/>
|
||||||
<FILE id="RU8fGr" name="MainComponent.h" compile="0" resource="0" file="Source/MainComponent.h"/>
|
<FILE id="RU8fGr" name="MainComponent.h" compile="0" resource="0" file="Source/MainComponent.h"/>
|
||||||
|
<FILE id="cFVaxu" name="MathUtil.h" compile="0" resource="0" file="Source/MathUtil.h"/>
|
||||||
<FILE id="eB92KJ" name="MidiComponent.cpp" compile="1" resource="0"
|
<FILE id="eB92KJ" name="MidiComponent.cpp" compile="1" resource="0"
|
||||||
file="Source/MidiComponent.cpp"/>
|
file="Source/MidiComponent.cpp"/>
|
||||||
<FILE id="GJqoJa" name="MidiComponent.h" compile="0" resource="0" file="Source/MidiComponent.h"/>
|
<FILE id="GJqoJa" name="MidiComponent.h" compile="0" resource="0" file="Source/MidiComponent.h"/>
|
||||||
|
|
Ładowanie…
Reference in New Issue