diff --git a/docs/2022-05-23_17.46.36.png b/docs/2022-05-23_17.46.36.png new file mode 100644 index 0000000..fc0b247 Binary files /dev/null and b/docs/2022-05-23_17.46.36.png differ diff --git a/docs/example.py b/docs/example.py new file mode 100644 index 0000000..9a8a44a --- /dev/null +++ b/docs/example.py @@ -0,0 +1,32 @@ +import matplotlib.pyplot as plt +import numpy as np +from math import comb + + +def B(n, k, t): + return comb(n, k) * t**k * (1 - t)**(n - k) + + +P = np.array([[0, 0], [0, 2], [1, 2], [1, 0], [1, -2], [2, -1], [2, 0]]) + +n = 3 + +S1 = np.array([sum(P[k] * B(n, k, t) for k in range(n + 1)) for t in np.linspace(0, 1, 100)]) +S2 = np.array([sum(P[k + n] * B(n, k, t) for k in range(n + 1)) for t in np.linspace(0, 1, 100)]) + +S1p = np.array([n * sum((P[k + 1] - P[k]) * B(n - 1, k, t) for k in range(n)) for t in np.linspace(0, 1, 100)]) +S2p = np.array([n * sum((P[k + 1 + n] - P[k + n]) * B(n - 1, k, t) for k in range(n)) for t in np.linspace(0, 1, 100)]) + +plt.subplot(121) +plt.plot(S1[:,0], S1[:,1]) +plt.plot(S2[:,0], S2[:,1]) +plt.plot(P[:,0], P[:,1], 'ro') +plt.axis('equal') + +plt.subplot(122) +plt.plot(S1p[:,0], S1p[:,1]) +plt.plot(S2p[:,0], S2p[:,1]) +plt.axis('equal') +plt.show() + + diff --git a/docs/rapport.md b/docs/rapport.md new file mode 100644 index 0000000..2b0d04d --- /dev/null +++ b/docs/rapport.md @@ -0,0 +1,69 @@ +

+Projet de Modélisation Géométrique
+Création et suivi de trajectoire de caméras
+Option longue 1 +

+ +

+Laurent Fainsin — +Damien Guillotin +

+ +## Description + +L’objectif de ce projet était de construire, à partir des connaissances acquises durant le cours d’interpolation et d’approximation, un module sous Unity3D qui permet de réaliser un suivi de trajectoire de caméra en ne fournissant qu’un nombre restreint d’informations, à savoir quelques points (trois coordonnées spatiales, trois coordonnées axiales). + +Nous avons décidé (avec l'accord de notre professeur, Julien Desvergnes) de modifier légèrement la consigne de ce projet. Nous avons opté pour le developpement d'un plugin pour un serveur [Minecraft](https://www.minecraft.net/fr-fr) [Spigot](https://www.spigotmc.org/), permettant aux joueurs de créer des travelings. + +## API Spigot + +L'API Spigot nous permet d'interfacer avec le monde / les propriétés / les entités de notre serveur Minecraft. + +Le serveur Minecraft ([paperMC](https://papermc.io/)) étant écrit en Java, nous devons utiliser ce langage de programmation pour développer notre plugin. + +Pour développer notre plugin nous avons donc créé un environnement de developpement sous VSCode via le gestionnaire de dépendance Java: [Gradle](https://gradle.org/). + +Pour compiler notre plugin nous pouvons générer une archive `.jar` via la commande `gradle jar`. Pour déployer notre plugin sur notre serveur, nous plaçons notre archive dans le dossier `plugins` de notre serveur. + +Pour améliorer le déployment et le lancement du serveur Minecraft, nous avons de plus utilisé un [docker-compose](https://docs.docker.com/compose/). + +Une fois le plugin déployé, et le serveur démarré, nous pouvons utiliser notre plugin. Si celui-ci n'est pas activé, nous pouvons utiliser la commande `/reload confirm` pour relancer les plugins. + +## Choix de courbe + +Pour le traveling de notre caméra, nous utilisons des courbes de Bezier. Pour réaliser la courbe complète, nous faisons suivre des courbes de degrés 3. + +La courbe finale s'apparente à une spline mais nous avons choisi ce type de modélisation car nous souhaitons que notre caméra passe exactement par certains points de contrôles (interpolation). Il est ainsi plus intuitif pour l'utilisateur de modifier la courbe. + +Ces courbes de bézier sont générées par évaluation, nous avons fait ce choix car la subdivision semblait peu adapté à la génération d'un nombre de point précis. De plus, le temps de calcule de la courbe reste négligeable, l'optimisation temporelle que permettrait la subdivision ne serait pas perceptible. + +Puisque la caméra dans Minecraft ne permet pas de rotation "row", nous avons directement interpolé nos rotations selon un schéma de bézier (sans passer par des quaternions). + +### Avantages / Inconvénients + + +### Démonstrations mathématiques + +on a fait quoi alors ? +k + +## Démonstrations + + + +## Conclusion + +Notre interpolation fonctionne bien, nos résultats sont satisfaisants. + +Seul bémol, notre serveur fonctionne assez lentement par rapport au serveur. +Tandis qu'un client Minecraft tourne au minimum à 60 fps, notre serveur étant monothreadé, celui-ci "tourne" plutôt aux alentoour des 15 fps (ou ticks). On obtient alors un rendu peu fluide dans certains cas. + +$\displaystyle B_k^n(t) = \binom{n}{k} t^k (1 - t)^{n-k}$ + +$\displaystyle S_i(t) = \sum_{k=0}^{n} P_i^k\ B_k^n(t)$ + +$\displaystyle S_i'(t) = n \sum_{k=0}^{n - 1} (P_i^{k + 1} - P_i^k)\ B_k^{n - 1}(t)$ + +$\displaystyle S_i'(1) = S_{i + 1}'(0)$ + +$\displaystyle n (P_i^{n} - P_i^{n - 1}) = n (P_{i + 1}^{1} - P_{i + 1}^{0})$ diff --git a/src/main/java/com/tocard/cam/Camera.java b/src/main/java/com/tocard/cam/Camera.java index ea2da7e..beda8e5 100644 --- a/src/main/java/com/tocard/cam/Camera.java +++ b/src/main/java/com/tocard/cam/Camera.java @@ -75,6 +75,9 @@ public class Camera extends JavaPlugin implements Listener { case BRICK: ClearPoints.clear(); break; + case BONE: + player.chat("/reset 0"); + break; default: break; } diff --git a/src/main/java/com/tocard/cam/ClearPoints.java b/src/main/java/com/tocard/cam/ClearPoints.java index 7a246b3..6fb7fb2 100644 --- a/src/main/java/com/tocard/cam/ClearPoints.java +++ b/src/main/java/com/tocard/cam/ClearPoints.java @@ -1,16 +1,26 @@ package com.tocard.cam; +import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.bukkit.util.BlockIterator; +import org.bukkit.util.Vector; public class ClearPoints implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (sender instanceof Player) { - clear(); + Player player = (Player) sender; + if (args.length == 0) { + clear(); + } else { + Vector dir = player.getLocation().getDirection(); + player.teleport(getTargetBlock(player, 100).getLocation().setDirection(dir).add(0, 1, 0)); + } } return true; } @@ -31,4 +41,17 @@ public class ClearPoints implements CommandExecutor { Camera.broadlog("All cleared !"); } + public static Block getTargetBlock(Player player, int range) { + BlockIterator iter = new BlockIterator(player, range); + Block lastBlock = iter.next(); + while (iter.hasNext()) { + lastBlock = iter.next(); + if (lastBlock.getType() == Material.AIR) { + continue; + } + break; + } + return lastBlock; + } + }