From e3a29a2945ac7f936d6313cf91508f896ad47e78 Mon Sep 17 00:00:00 2001
From: netpro2k <netpro2k@gmail.com>
Date: Fri, 13 Oct 2017 12:57:45 -0700
Subject: [PATCH] Randomize avatar color

---
 package.json                                  |   1 +
 .../DodecAvatarGLTF/AvatarDodeca_Texture.png  | Bin 20775 -> 5591 bytes
 public/index.html                             |   9 +++-
 src/components/avatar-customization.js        |  49 ++++++++++++++++++
 src/index.js                                  |   1 +
 yarn.lock                                     |   4 ++
 6 files changed, 63 insertions(+), 1 deletion(-)
 create mode 100644 src/components/avatar-customization.js

diff --git a/package.json b/package.json
index 63296bff9..9ff615051 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
     "easyrtc": "^1.1.0",
     "express": "^4.15.5",
     "networked-aframe": "https://github.com/netpro2k/networked-aframe#dev",
+    "pleasejs": "^0.4.2",
     "socket.io": "^2.0.3"
   },
   "devDependencies": {
diff --git a/public/assets/avatars/dodec/DodecAvatarGLTF/AvatarDodeca_Texture.png b/public/assets/avatars/dodec/DodecAvatarGLTF/AvatarDodeca_Texture.png
index d0f89bc1497e8bc97c7c035abde9705e1316b613..3f7585fbd2ec32b717296daedb765cad19b9daa7 100644
GIT binary patch
literal 5591
zcmeAS@N?(olHy`uVBq!ia0y~yU;#2&7&zE~RK2WrGmv6S@^*J&_z!{$_AZ|c6yYrJ
zh%9Dc;1&j9Muu5)B!GhKC7!;n><_uP8Q2u3`FZ_kU=U65ba4!+xb^ndM&1Jo0xXWn
z7Y}duX1uQ}$+_;(q>tyP6g+%&OCmX*!9lawPnp5Na62c^90wqVID;@#0IZe~L=t3z
zJVw|=2aqZT;!H%cl17F@Tr&s^NAfChOj2A<oQaS~AtfxpYH4LSB8fC?E)`~Qu$`I7
z!k}@C8I*iTaU{YVf~k(QF!cesgb73_fCz%j2Cym)5J`}!08&NJM2G_7Ol$y~2v(~A
zW)kOeQVb`~L?qj3WOxJEe}lkqB(D<3B*o>#nK+t6u%=2<0ve(gt1;MfC@F@M5{qE9
zv@#q|b~&(m7bnAlc^w8!3?h%g#pxgj3=Rf01|XnW=}x@iq*O+9sxgTS7E)YJqkwh*
zg)@=P1-CRH8i;c_Qq#mDCOSLU7--dj{goga8$bjDo<xtNKmnu_dsfE~CC<bKh=~oO
z&2dmbAd;2?I9!N}T!>nPUL<3%Gf6QVDdiByq?O^MgaueFan6N=5GjU}5YRL=oRokb
zO(F~+fF8}GNdyrr0t}<wI8bOH)mtPq?nv)lkYIQNIF^tcMvzG(!@=$tB}QZj9B8*~
WlNK_p-Td@3$p4<MelF{r5}E+9kf?kB

literal 20775
zcmeI4UuYaf9LImVw|8tVIozgak~T=U(UNFV?<#_{d2kahnkXb!Db(7U9BMEv5&}Yq
z0m)vPYN}$>pm|Z~1rhYY&;}n$ZDGk%O;OXAA{rq`2!%!qc}W5i{O$eOnTd}@jPQNB
zVQyx2@4LT0pZU#l=hL0f$D(_qL=@|2PrXEBaMK_&!XG1#G@d20sUy{LY)D)EW%}Vc
zC!V?;s}JYeWAP8BTjnV{*L39I>UUR{R(?GG_TXnf9eRJCrW>YZPgD-QJM;DRxk}q{
zNz-3HWm|=o|7E`GUU?1Ox&Lx&et5pe|7t1h)@~aZ))Evwc&puCCz$<?7IL->QWkYu
zJWBVScutJs;Wzm*YxSf|HlljOZN2qW@#YGPI^7;kJgZS~3BQrHk`#Ys>Y{vUV~uD3
zRYuBfW=CBuw=nyWGJB#rNy}ZNOg7_21)ZDfeJuFN+{j*cHG4#-k~aBOa(0FqzHNF`
z`qhTH9Il|v-6T)e^e~Gt-MgnuR>MwY=;kFNMT`cs22z%u8>Ezs6;>%Z3LIP#1F=#H
zz(_li7)U!Jvm=8`g!Qk$(B<mZ`62^;9{%&f`sPDDh5Y5M>D|=SbH$a?8Iw?^BIGuf
za($7EGzO*I8@m)xa$U`f$>hX1#(j2rc3fT1qos%fXs+XUWHp>fNzsxAWN09y&a}DD
z{G_Q)@*N(Kq^oL&ZE>IRLX}FJjBJa-&hj%%?$Zx^s1h+_Wxw<c{DB7dWhdJd)YS9{
zJ)`2Ip)=4r-`6QPOj_t4Bo6ubK|nrOADkDl&rcah9Y`IVXpwmVF5o_3bAGo0Y{ss`
zz@`m*UIs*z3{Wya$-uN8tYFow7Yb~-`hmrdyZg@P%XiKxuiV|x#=Df7SBwjMU%dIa
zQsA?n%+UBgcSEVkEikb@Jv=q3RMvjyIvAEL)i@O`yT)EyFTD#;tXe|Xl2X29!Jvv}
zk@rV<k{nnRPlER#9E)QqgbjoZRsivG=fumOSME309{qCLsp+fy7UH$vUhGtGb3fze
zS8p9va5LAKp}T{L!?InQV_XxNo^3lIAG~H~_?5w5Z!9ZZYE>p_Y`*GKSq|eGb7}wj
z<Zcl*9M@^*v*#yH9#hVq??!8IlSS#Eq%bzvq;Oj}j)*M?K~j`PFc+B!8At5xk-Np)
zaR3a#U;qpN2I3^*BsO9JM1dy*DKs5C37$kPDA;Ub-yKLnh?9tu|KIIH{F^iH5m|Tq
z{{;X51Aqa*K{P{P52OG9OH$wnPwWM77%EbRwbKf!f>CAbm2OznKSlLV9IjzH^pQMW
z92`Iv$b#SiFMt=o3;s(l*!pAP3jehsdG^S?)2j_*6*b9>=W3xyp^^Q;sqWa7XdJ$r
P@JDsDb*5%oGoyb4Aj~<0

diff --git a/public/index.html b/public/index.html
index 3125bcf20..956d5c4c2 100644
--- a/public/index.html
+++ b/public/index.html
@@ -26,7 +26,14 @@
 
       <!-- Templates -->
       <script id="head-template" type="text/html">
-        <a-entity class="head" gltf-model="#dodec-avatar-head" position="0 0 0" networked-audio-source audio-feedback></a-entity>
+        <a-entity
+            class="head"
+            gltf-model="#dodec-avatar-head"
+            position="0 0 0"
+            networked-audio-source
+            audio-feedback
+            avatar-customization
+        ></a-entity>
       </script>
 
       <script id="hand-template" type="text/html">
diff --git a/src/components/avatar-customization.js b/src/components/avatar-customization.js
new file mode 100644
index 000000000..8346b8e82
--- /dev/null
+++ b/src/components/avatar-customization.js
@@ -0,0 +1,49 @@
+import Please from "pleasejs";
+
+// @TODO this whole thing is a bit of a hack. This should probably just be setting some uniforms on a sharder.
+// @TODO the palate should be indexed by alpha channel instead of the red channel.
+// @TODO color should be multiplied with the texture value to allow for texture to provide surface detail.
+// @TODO texture should be regenerated whenever headColor/LidColor values change to allow for networking, though arguably these will eventually be fetched from a users "profile" anywya, so might not be worth trying to network through NAF.
+AFRAME.registerComponent("avatar-customization", {
+  schema: {
+    headColor: { type: "color", default: null },
+    lidColor: { type: "color", default: null }
+  },
+
+  init: function() {
+    const colors = Please.make_color({
+      format: "rgb-string",
+      colors_returned: 2
+    });
+
+    this.colorMap = new Map();
+    this.colorMap.set(128, this.data.headColor || new THREE.Color(colors[0]));
+    this.colorMap.set(115, this.data.lidColor || new THREE.Color(colors[1]));
+
+    this.el.addEventListener("model-loaded", () => {
+      const map = this.el.object3D.getObjectByName("DodecAvatar_Head_0")
+        .material.map;
+      const img = map.image;
+
+      const canvas = document.createElement("canvas");
+      canvas.width = img.width;
+      canvas.height = img.height;
+      const ctx = canvas.getContext("2d");
+      ctx.drawImage(img, 0, 0, img.width, img.height);
+      const imageData = ctx.getImageData(0, 0, img.width, img.height);
+      const pixelData = imageData.data;
+
+      for (let i = 0; i < pixelData.length; i += 4) {
+        // @TODO check alpha channel and multiply colors to preserver surface detail
+        if (this.colorMap.has(pixelData[i])) {
+          const color = this.colorMap.get(pixelData[i]);
+          pixelData[i] = color.r * 255;
+          pixelData[i + 1] = color.g * 255;
+          pixelData[i + 2] = color.b * 255;
+        }
+      }
+      ctx.putImageData(imageData, 0, 0);
+      map.image = canvas;
+    });
+  }
+});
diff --git a/src/index.js b/src/index.js
index e1f40da05..1c226e589 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,6 +6,7 @@ import "./components/snap-rotation";
 import "./components/mute-mic";
 import "./components/audio-feedback";
 import "./components/nametag-transform";
+import "./components/avatar-customization";
 
 import { generateName } from "./utils";
 
diff --git a/yarn.lock b/yarn.lock
index f7eeb63a0..5a60e56fe 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2090,6 +2090,10 @@ pify@^2.0.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
 
+pleasejs@^0.4.2:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/pleasejs/-/pleasejs-0.4.2.tgz#aaaa1a5fa6902518de7e51e3c63b5f537f823164"
+
 preserve@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-- 
GitLab