Google Sheets Apply formula based on cell value - if-statement
We use Google Sheets to bid for work schedules. Bidding is done in groups. Sheet1 contains the employee PIN with their shift preferences (1-16) based on seniority. Column U contains the IF/AND formula used to assign the employee to a shift based on availability and preference. Column V contains the employees bidding group # based on the formula.
As it stands, I use the fill handle to drag the formula in Column U down by group, starting with group 1. When it is group 2’s turn to bid then I drag the formula down through group 2...so on and so forth. What I would like is for the formula to automatically drag down (or appear) for the group when I select "Yes" on the 'Live Bid' sheet under the group #. As I move from group to group, I need the previous groups formula to still show so the formula in column U is correct.
Hope this makes sense.
Demo Link
paste in U2:
=ARRAYFORMULA(
IF(((H5:H="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), H5:H,
IF(((H5:H="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), H5:H,
IF(((H5:H="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), H5:H,
IF(((H5:H="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), H5:H,
IF(((H5:H="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), H5:H,
IF(((H5:H="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), H5:H,
IF(((H5:H="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), H5:H,
IF(((H5:H="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), H5:H,
IF(((H5:H="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), H5:H,
IF(((H5:H="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), H5:H,
IF(((H5:H="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), H5:H,
IF(((H5:H="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), H5:H,
IF(((H5:H="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), H5:H,
IF(((H5:H="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), H5:H,
IF(((H5:H="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), H5:H,
IF(((H5:H="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), H5:H,
IF(((I5:I="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), I5:I,
IF(((I5:I="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), I5:I,
IF(((I5:I="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), I5:I,
IF(((I5:I="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), I5:I,
IF(((I5:I="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), I5:I,
IF(((I5:I="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), I5:I,
IF(((I5:I="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), I5:I,
IF(((I5:I="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), I5:I,
IF(((I5:I="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), I5:I,
IF(((I5:I="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), I5:I,
IF(((I5:I="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), I5:I,
IF(((I5:I="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), I5:I,
IF(((I5:I="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), I5:I,
IF(((I5:I="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), I5:I,
IF(((I5:I="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), I5:I,
IF(((I5:I="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), I5:I,
IF(((J5:J="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), J5:J,
IF(((J5:J="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), J5:J,
IF(((J5:J="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), J5:J,
IF(((J5:J="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), J5:J,
IF(((J5:J="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), J5:J,
IF(((J5:J="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), J5:J,
IF(((J5:J="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), J5:J,
IF(((J5:J="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), J5:J,
IF(((J5:J="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), J5:J,
IF(((J5:J="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), J5:J,
IF(((J5:J="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), J5:J,
IF(((J5:J="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), J5:J,
IF(((J5:J="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), J5:J,
IF(((J5:J="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), J5:J,
IF(((J5:J="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), J5:J,
IF(((J5:J="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), J5:J,
IF(((K5:K="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), K5:K,
IF(((K5:K="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), K5:K,
IF(((K5:K="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), K5:K,
IF(((K5:K="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), K5:K,
IF(((K5:K="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), K5:K,
IF(((K5:K="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), K5:K,
IF(((K5:K="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), K5:K,
IF(((K5:K="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), K5:K,
IF(((K5:K="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), K5:K,
IF(((K5:K="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), K5:K,
IF(((K5:K="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), K5:K,
IF(((K5:K="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), K5:K,
IF(((K5:K="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), K5:K,
IF(((K5:K="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), K5:K,
IF(((K5:K="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), K5:K,
IF(((K5:K="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), K5:K,
IF(((L5:L="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), L5:L,
IF(((L5:L="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), L5:L,
IF(((L5:L="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), L5:L,
IF(((L5:L="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), L5:L,
IF(((L5:L="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), L5:L,
IF(((L5:L="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), L5:L,
IF(((L5:L="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), L5:L,
IF(((L5:L="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), L5:L,
IF(((L5:L="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), L5:L,
IF(((L5:L="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), L5:L,
IF(((L5:L="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), L5:L,
IF(((L5:L="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), L5:L,
IF(((L5:L="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), L5:L,
IF(((L5:L="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), L5:L,
IF(((L5:L="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), L5:L,
IF(((L5:L="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), L5:L,
IF(((M5:M="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), M5:M,
IF(((M5:M="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), M5:M,
IF(((M5:M="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), M5:M,
IF(((M5:M="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), M5:M,
IF(((M5:M="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), M5:M,
IF(((M5:M="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), M5:M,
IF(((M5:M="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), M5:M,
IF(((M5:M="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), M5:M,
IF(((M5:M="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), M5:M,
IF(((M5:M="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), M5:M,
IF(((M5:M="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), M5:M,
IF(((M5:M="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), M5:M,
IF(((M5:M="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), M5:M,
IF(((M5:M="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), M5:M,
IF(((M5:M="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), M5:M,
IF(((M5:M="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), M5:M,
IF(((N5:N="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), N5:N,
IF(((N5:N="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), N5:N,
IF(((N5:N="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), N5:N,
IF(((N5:N="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), N5:N,
IF(((N5:N="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), N5:N,
IF(((N5:N="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), N5:N,
IF(((N5:N="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), N5:N,
IF(((N5:N="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), N5:N,
IF(((N5:N="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), N5:N,
IF(((N5:N="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), N5:N,
IF(((N5:N="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), N5:N,
IF(((N5:N="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), N5:N,
IF(((N5:N="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), N5:N,
IF(((N5:N="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), N5:N,
IF(((N5:N="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), N5:N,
IF(((N5:N="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), N5:N,
IF(((O5:O="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), O5:O,
IF(((O5:O="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), O5:O,
IF(((O5:O="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), O5:O,
IF(((O5:O="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), O5:O,
IF(((O5:O="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), O5:O,
IF(((O5:O="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), O5:O,
IF(((O5:O="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), O5:O,
IF(((O5:O="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), O5:O,
IF(((O5:O="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), O5:O,
IF(((O5:O="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), O5:O,
IF(((O5:O="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), O5:O,
IF(((O5:O="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), O5:O,
IF(((O5:O="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), O5:O,
IF(((O5:O="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), O5:O,
IF(((O5:O="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), O5:O,
IF(((O5:O="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), O5:O,
IF(((P5:P="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), P5:P,
IF(((P5:P="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), P5:P,
IF(((P5:P="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), P5:P,
IF(((P5:P="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), P5:P,
IF(((P5:P="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), P5:P,
IF(((P5:P="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), P5:P,
IF(((P5:P="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), P5:P,
IF(((P5:P="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), P5:P,
IF(((P5:P="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), P5:P,
IF(((P5:P="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), P5:P,
IF(((P5:P="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), P5:P,
IF(((P5:P="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), P5:P,
IF(((P5:P="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), P5:P,
IF(((P5:P="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), P5:P,
IF(((P5:P="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), P5:P,
IF(((P5:P="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), P5:P,
IF(((Q5:Q="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), Q5:Q,
IF(((Q5:Q="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), Q5:Q,
IF(((Q5:Q="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), Q5:Q,
IF(((Q5:Q="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), Q5:Q,
IF(((Q5:Q="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), Q5:Q,
IF(((Q5:Q="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), Q5:Q,
IF(((Q5:Q="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), Q5:Q,
IF(((Q5:Q="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), Q5:Q,
IF(((Q5:Q="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), Q5:Q,
IF(((Q5:Q="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), Q5:Q,
IF(((Q5:Q="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), Q5:Q,
IF(((Q5:Q="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), Q5:Q,
IF(((Q5:Q="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), Q5:Q,
IF(((Q5:Q="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), Q5:Q,
IF(((Q5:Q="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), Q5:Q,
IF(((Q5:Q="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), Q5:Q,
IF(((R5:R="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), R5:R,
IF(((R5:R="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), R5:R,
IF(((R5:R="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), R5:R,
IF(((R5:R="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), R5:R,
IF(((R5:R="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), R5:R,
IF(((R5:R="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), R5:R,
IF(((R5:R="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), R5:R,
IF(((R5:R="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), R5:R,
IF(((R5:R="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), R5:R,
IF(((R5:R="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), R5:R,
IF(((R5:R="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), R5:R,
IF(((R5:R="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), R5:R,
IF(((R5:R="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), R5:R,
IF(((R5:R="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), R5:R,
IF(((R5:R="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), R5:R,
IF(((R5:R="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), R5:R,
IF(((S5:S="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), S5:S,
IF(((S5:S="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), S5:S,
IF(((S5:S="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), S5:S,
IF(((S5:S="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), S5:S,
IF(((S5:S="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), S5:S,
IF(((S5:S="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), S5:S,
IF(((S5:S="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), S5:S,
IF(((S5:S="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), S5:S,
IF(((S5:S="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), S5:S,
IF(((S5:S="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), S5:S,
IF(((S5:S="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), S5:S,
IF(((S5:S="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), S5:S,
IF(((S5:S="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), S5:S,
IF(((S5:S="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), S5:S,
IF(((S5:S="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), S5:S,
IF(((S5:S="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), S5:S,
IF(((T5:T="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), T5:T,
IF(((T5:T="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), T5:T,
IF(((T5:T="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), T5:T,
IF(((T5:T="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), T5:T,
IF(((T5:T="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), T5:T,
IF(((T5:T="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), T5:T,
IF(((T5:T="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), T5:T,
IF(((T5:T="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), T5:T,
IF(((T5:T="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), T5:T,
IF(((T5:T="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), T5:T,
IF(((T5:T="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), T5:T,
IF(((T5:T="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), T5:T,
IF(((T5:T="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), T5:T,
IF(((T5:T="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), T5:T,
IF(((T5:T="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), T5:T,
IF(((T5:T="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), T5:T,
IF(((U5:U="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), U5:U,
IF(((U5:U="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), U5:U,
IF(((U5:U="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), U5:U,
IF(((U5:U="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), U5:U,
IF(((U5:U="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), U5:U,
IF(((U5:U="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), U5:U,
IF(((U5:U="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), U5:U,
IF(((U5:U="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), U5:U,
IF(((U5:U="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), U5:U,
IF(((U5:U="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), U5:U,
IF(((U5:U="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), U5:U,
IF(((U5:U="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), U5:U,
IF(((U5:U="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), U5:U,
IF(((U5:U="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), U5:U,
IF(((U5:U="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), U5:U,
IF(((U5:U="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), U5:U,
IF(((V5:V="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), V5:V,
IF(((V5:V="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), V5:V,
IF(((V5:V="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), V5:V,
IF(((V5:V="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), V5:V,
IF(((V5:V="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), V5:V,
IF(((V5:V="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), V5:V,
IF(((V5:V="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), V5:V,
IF(((V5:V="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), V5:V,
IF(((V5:V="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), V5:V,
IF(((V5:V="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), V5:V,
IF(((V5:V="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), V5:V,
IF(((V5:V="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), V5:V,
IF(((V5:V="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), V5:V,
IF(((V5:V="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), V5:V,
IF(((V5:V="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), V5:V,
IF(((V5:V="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), V5:V,
IF(((W5:W="1N1 TWT(F)") * (COUNTIF(X3, "1N1 TWT(F)")<7)), W5:W,
IF(((W5:W="1N2 (F)SSM") * (COUNTIF(X3, "1N2 (F)SSM")<7)), W5:W,
IF(((W5:W="1S1 (S)MTW") * (COUNTIF(X3, "1S1 (S)MTW")<7)), W5:W,
IF(((W5:W="1S2 TFS(S)") * (COUNTIF(X3, "1S2 TFS(S)")<7)), W5:W,
IF(((W5:W="2N1 FSS(M)") * (COUNTIF(X3, "2N1 FSS(M)")<5)), W5:W,
IF(((W5:W="2N1 MIDS") * (COUNTIF(X3, "2N1 MIDS")<2)), W5:W,
IF(((W5:W="2N2 (M)TWT") * (COUNTIF(X3, "2N2 (M)TWT")<4)), W5:W,
IF(((W5:W="2N2 MIDS") * (COUNTIF(X3, "2N2 MIDS")<2)), W5:W,
IF(((W5:W="2S1 (S)SMT") * (COUNTIF(X3, "2S1 (S)SMT")<4)), W5:W,
IF(((W5:W="2S1 MIDS") * (COUNTIF(X3, "2S1 MIDS")<2)), W5:W,
IF(((W5:W="2S2 WTF(S)") * (COUNTIF(X3, "2S2 WTF(S)")<4)), W5:W,
IF(((W5:W="2S2 MIDS") * (COUNTIF(X3, "2S2 MIDS")<2)), W5:W,
IF(((W5:W="3N1 (T)FSS") * (COUNTIF(X3, "3N1 (T)FSS")<6)), W5:W,
IF(((W5:W="3N2 MTW(T)") * (COUNTIF(X3, "3N2 MTW(T)")<6)), W5:W,
IF(((W5:W="3S1 (S)SMT") * (COUNTIF(X3, "3S1 (S)SMT")<6)), W5:W,
IF(((W5:W="3S2 WTF(S)") * (COUNTIF(X3, "3S2 WTF(S)")<6)), W5:W,
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
))))))))))))))))))))))))))))))))
Related
OpenGL Triangle pipe around line segment
I would like to ask how can I render in geometry shader a triangle pipe from a line segment? I first compute perpendicular vector "perp" to the line vector "axis". Then I rotate the "perp" vector few times by "rotate" function. Since mesh is composed from 8 vertices I am trying to use "triangle_strip". My current code : #version 330 core layout (lines) in; layout(triangle_strip, max_vertices = 8) out;//triangle_strip uniform float u_thickness ; uniform vec2 u_viewportSize ; uniform bool u_scale_width_by_zoom ; in gl_PerVertex { vec4 gl_Position; //float gl_PointSize; //float gl_ClipDistance[]; } gl_in[]; vec4 rotate(vec4 p, float x, float y, float z,float angle ) { vec3 q; q[0] = p[0] * (x*x * (1.0 - cos(angle)) + cos(angle)) + p[1] * (x*y * (1.0 - cos(angle)) + z * sin(angle)) + p[2] * (x*z * (1.0 - cos(angle)) - y * sin(angle)); q[1] = p[0] * (y*x * (1.0 - cos(angle)) - z * sin(angle)) + p[1]* (y*y * (1.0 - cos(angle)) + cos(angle)) + p[2] * (y*z * (1.0 - cos(angle)) + x * sin(angle)); q[2] = p[0] * (z*x * (1.0 - cos(angle)) + y * sin(angle)) + p[1] * (z*y * (1.0 - cos(angle)) - x * sin(angle)) + p[2] * (z*z * (1.0 - cos(angle)) + cos(angle)); return vec4(q, 0.0); } void main() { //https://stackoverflow.com/questions/54686818/glsl-geometry-shader-to-replace-gllinewidth vec4 p1 = gl_in[0].gl_Position; vec4 p2 = gl_in[1].gl_Position; //tube // Specify the axis to rotate about: vec4 axis = p2-p1; float x = axis[0]; float y = axis[1]; float z = axis[2]; axis = normalize(axis); //float length = hypotf(axis[0], hypotf(axis[1], axis[2])); float length = sqrt((axis[0]*axis[0]) + sqrt(axis[1]*axis[1]+ axis[2]*axis[2])); float dir_scalar = (axis[0] > 0.0) ? length : -length; float xt = axis[0] + dir_scalar; float dot = -axis[1] / (dir_scalar * xt); vec3 perp_0 = vec3(dot * xt, 1.0f + dot * axis.y, dot * axis.z); perp_0 = normalize(perp_0); vec4 perp = vec4(perp_0,0)*u_thickness*0.001; //side0 vec4 p1_1 = p1+perp; vec4 p1_2 = p2+perp; vec4 perp_rot_2=rotate(perp,x,y,z,60.0 * 3.14 / 180.0); vec4 p2_1 = p1+perp_rot_2; vec4 p2_2 = p2+perp_rot_2; vec4 perp_rot_3=rotate(perp,x,y,z, 120.0 * 3.14 / 180.0); vec4 p3_1 = p1+perp_rot_3; vec4 p3_2 = p2+perp_rot_3; gl_Position = p1_1; EmitVertex(); gl_Position = p1_2; EmitVertex(); gl_Position = p2_1; EmitVertex(); gl_Position = p2_2; EmitVertex(); gl_Position = p3_1; EmitVertex(); gl_Position = p3_2; EmitVertex(); gl_Position = p1_1; EmitVertex(); gl_Position = p1_2; EmitVertex(); EndPrimitive(); } It produces wrong results:
matrix inversion help for opengl errors
I am trying to get the inverse of a 4x4 square matrix for opengl, so it is a column major matrix. Also I would like to avoid discussions about making my code into loops, it's quite challenging enough to follow without loops. I wrote some code that can do most basic matrix operations but matrix inverse was kinda rough, I found this answer: inverting a 4x4 matrix I implemented it in my code void mat4inverse(mat4* out, const mat4* in) { double inv[16], det; int i; inv[0] = in->m[5] * in->m[10] * in->m[15] - in->m[5] * in->m[11] * in->m[14] - in->m[9] * in->m[6] * in->m[15] + in->m[9] * in->m[7] * in->m[14] + in->m[13] * in->m[6] * in->m[11] - in->m[13] * in->m[7] * in->m[10]; inv[4] = -in->m[4] * in->m[10] * in->m[15] + in->m[4] * in->m[11] * in->m[14] + in->m[8] * in->m[6] * in->m[15] - in->m[8] * in->m[7] * in->m[14] - in->m[12] * in->m[6] * in->m[11] + in->m[12] * in->m[7] * in->m[10]; inv[8] = in->m[4] * in->m[9] * in->m[15] - in->m[4] * in->m[11] * in->m[13] - in->m[8] * in->m[5] * in->m[15] + in->m[8] * in->m[7] * in->m[13] + in->m[12] * in->m[5] * in->m[11] - in->m[12] * in->m[7] * in->m[9]; inv[12] = -in->m[4] * in->m[9] * in->m[14] + in->m[4] * in->m[10] * in->m[13] + in->m[8] * in->m[5] * in->m[14] - in->m[8] * in->m[6] * in->m[13] - in->m[12] * in->m[5] * in->m[10] + in->m[12] * in->m[6] * in->m[9]; inv[1] = -in->m[1] * in->m[10] * in->m[15] + in->m[1] * in->m[11] * in->m[14] + in->m[9] * in->m[2] * in->m[15] - in->m[9] * in->m[3] * in->m[14] - in->m[13] * in->m[2] * in->m[11] + in->m[13] * in->m[3] * in->m[10]; inv[5] = in->m[0] * in->m[10] * in->m[15] - in->m[0] * in->m[11] * in->m[14] - in->m[8] * in->m[2] * in->m[15] + in->m[8] * in->m[3] * in->m[14] + in->m[12] * in->m[2] * in->m[11] - in->m[12] * in->m[3] * in->m[10]; inv[9] = -in->m[0] * in->m[9] * in->m[15] + in->m[0] * in->m[11] * in->m[13] + in->m[8] * in->m[1] * in->m[15] - in->m[8] * in->m[3] * in->m[13] - in->m[12] * in->m[1] * in->m[11] + in->m[12] * in->m[3] * in->m[9]; inv[13] = in->m[0] * in->m[9] * in->m[14] - in->m[0] * in->m[10] * in->m[13] - in->m[8] * in->m[1] * in->m[14] + in->m[8] * in->m[2] * in->m[13] + in->m[12] * in->m[1] * in->m[10] - in->m[12] * in->m[2] * in->m[9]; inv[2] = in->m[1] * in->m[6] * in->m[15] - in->m[1] * in->m[7] * in->m[14] - in->m[5] * in->m[2] * in->m[15] + in->m[5] * in->m[3] * in->m[14] + in->m[13] * in->m[2] * in->m[7] - in->m[13] * in->m[3] * in->m[6]; inv[6] = -in->m[0] * in->m[6] * in->m[15] + in->m[0] * in->m[7] * in->m[14] + in->m[4] * in->m[2] * in->m[15] - in->m[4] * in->m[3] * in->m[14] - in->m[12] * in->m[2] * in->m[7] + in->m[12] * in->m[3] * in->m[6]; inv[10] = in->m[0] * in->m[5] * in->m[15] - in->m[0] * in->m[7] * in->m[13] - in->m[4] * in->m[1] * in->m[15] + in->m[4] * in->m[3] * in->m[13] + in->m[12] * in->m[1] * in->m[7] - in->m[12] * in->m[3] * in->m[5]; inv[14] = -in->m[0] * in->m[5] * in->m[14] + in->m[0] * in->m[6] * in->m[13] + in->m[4] * in->m[1] * in->m[14] - in->m[4] * in->m[2] * in->m[13] - in->m[12] * in->m[1] * in->m[6] + in->m[12] * in->m[2] * in->m[5]; inv[3] = -in->m[1] * in->m[6] * in->m[11] + in->m[1] * in->m[7] * in->m[10] + in->m[5] * in->m[2] * in->m[11] - in->m[5] * in->m[3] * in->m[10] - in->m[9] * in->m[2] * in->m[7] + in->m[9] * in->m[3] * in->m[6]; inv[7] = in->m[0] * in->m[6] * in->m[11] - in->m[0] * in->m[7] * in->m[10] - in->m[4] * in->m[2] * in->m[11] + in->m[4] * in->m[3] * in->m[10] + in->m[8] * in->m[2] * in->m[7] - in->m[8] * in->m[3] * in->m[6]; inv[11] = -in->m[0] * in->m[5] * in->m[11] + in->m[0] * in->m[7] * in->m[9] + in->m[4] * in->m[1] * in->m[11] - in->m[4] * in->m[3] * in->m[9] - in->m[8] * in->m[1] * in->m[7] + in->m[8] * in->m[3] * in->m[5]; inv[15] = in->m[0] * in->m[5] * in->m[10] - in->m[0] * in->m[6] * in->m[9] - in->m[4] * in->m[1] * in->m[10] + in->m[4] * in->m[2] * in->m[9] + in->m[8] * in->m[1] * in->m[6] - in->m[8] * in->m[2] * in->m[5]; det = in->m[0] * inv[0] + in->m[1] * inv[4] + in->m[2] * inv[8] + in->m[3] * inv[12]; if (det == 0) printf("oh oh!"); det = 1.0 / det; //printf("\n\ndeterminant:%f\n\n",det); for (i = 0; i < 16; i++) out->m[i] = inv[i] * det; } I create a matrix that looks like this: [ 1.000000 3.000000 4.000000 9.000000 ] [ 5.000000 6.000000 7.000000 2.000000 ] [ 8.000000 8.000000 8.000000 9.000000 ] [ 0.000000 0.000000 0.000000 1.000000 ] after passing it to my transpose function that I listed above the results are: [ -1.000000 1.000000 -0.375000 10.375000 ] [ 2.000000 -3.000000 1.625000 -26.625000 ] [ -1.000000 2.000000 -1.125000 15.125000 ] [ 0.000000 0.000000 0.000000 1.000000 ] I am not sure but that seems a bit wrong to me. This is for opengl rendering and my matrix is a 1D 16 double array. Am I getting correct results? additional info Here is my math over on code review: https://codereview.stackexchange.com/questions/98692/4d-matrix-math-library-for-use-with-opengl
OpenGL Matrix Multiplication C++
So I am trying to multiply rotation and translation matrices together and I can't quite figure out what is going wrong. If, in the program I multiply a translation matrix by a rotation matrix then send that matrix as a uniform to my shader program I end up with the object becoming 2D then 3D again as it spins [ https://a.pomf.se/xvvrsg.mp4 ] (object on the right). shader.setUniformMat4("model_matrix", Matrix4::translation(Vector3(10.0f, 0.0f, 0.0f)) * Matrix4::rotation(rotation, Vector3(0.0f, 1.0f, 0.0f))); (vertex shader) #version 330 core layout (location = 0) in vec4 in_position; layout (location = 1) in vec4 in_normal; uniform mat4 pr_matrix; uniform mat4 vw_matrix = mat4(1.0); uniform mat4 model_matrix = mat4(1.0); out vec4 pos; out vec4 normal; void main() { pos = pr_matrix * vw_matrix * model_matrix * in_position; normal = in_normal; gl_Position = pos; } However if I send my individual translation and rotation matrices as separate uniforms and then multiply them in the shader to create my model matrix it works as intended [ https://a.pomf.se/jyxpnb.mp4 ] (object on the right). shader.setUniformMat4("translation_matrix", Matrix4::translation(Vector3(10.0f, 0.0f, 0.0f))); shader.setUniformMat4("rotation_matrix", Matrix4::rotation(rotation, Vector3(0.0f, 1.0f, 0.0f))); shader.setUniformMat4("scale_matrix", Matrix4::identity()); (vertex shader) #version 330 core layout (location = 0) in vec4 in_position; layout (location = 1) in vec4 in_normal; uniform mat4 pr_matrix; uniform mat4 vw_matrix = mat4(1.0); uniform mat4 translation_matrix = mat4(1.0); uniform mat4 rotation_matrix = mat4(1.0); uniform mat4 scale_matrix = mat4(1.0); out vec4 pos; out vec4 normal; void main() { mat4 model_matrix = translation_matrix * rotation_matrix * scale_matrix; pos = pr_matrix * vw_matrix * model_matrix * in_position; normal = in_normal; gl_Position = pos; } This leads me to believe that there must be an error in my multiplication of matrices, this is how I am currently doing it: Matrix4 &Matrix4::multiply(const Matrix4 &other) { elements[0] = elements[0] * other.elements[0] + elements[4] * other.elements[1] + elements[8] * other.elements[2] + elements[12] * other.elements[3]; elements[1] = elements[1] * other.elements[0] + elements[5] * other.elements[1] + elements[9] * other.elements[2] + elements[13] * other.elements[3]; elements[2] = elements[2] * other.elements[0] + elements[6] * other.elements[1] + elements[10] * other.elements[2] + elements[14] * other.elements[3]; elements[3] = elements[3] * other.elements[0] + elements[7] * other.elements[1] + elements[11] * other.elements[2] + elements[15] * other.elements[3]; elements[4] = elements[0] * other.elements[4] + elements[4] * other.elements[5] + elements[8] * other.elements[6] + elements[12] * other.elements[7]; elements[5] = elements[1] * other.elements[4] + elements[5] * other.elements[5] + elements[9] * other.elements[6] + elements[13] * other.elements[7]; elements[6] = elements[2] * other.elements[4] + elements[6] * other.elements[5] + elements[10] * other.elements[6] + elements[14] * other.elements[7]; elements[7] = elements[3] * other.elements[4] + elements[7] * other.elements[5] + elements[11] * other.elements[6] + elements[15] * other.elements[7]; elements[8] = elements[0] * other.elements[8] + elements[4] * other.elements[9] + elements[8] * other.elements[10] + elements[12] * other.elements[11]; elements[9] = elements[1] * other.elements[8] + elements[5] * other.elements[9] + elements[9] * other.elements[10] + elements[13] * other.elements[11]; elements[10] = elements[2] * other.elements[8] + elements[6] * other.elements[9] + elements[10] * other.elements[10] + elements[14] * other.elements[11]; elements[11] = elements[3] * other.elements[8] + elements[7] * other.elements[9] + elements[11] * other.elements[10] + elements[15] * other.elements[11]; elements[12] = elements[0] * other.elements[12] + elements[4] * other.elements[13] + elements[8] * other.elements[14] + elements[12] * other.elements[15]; elements[13] = elements[1] * other.elements[12] + elements[5] * other.elements[13] + elements[9] * other.elements[14] + elements[13] * other.elements[15]; elements[14] = elements[2] * other.elements[12] + elements[6] * other.elements[13] + elements[10] * other.elements[14] + elements[14] * other.elements[15]; elements[15] = elements[3] * other.elements[12] + elements[7] * other.elements[13] + elements[11] * other.elements[14] + elements[15] * other.elements[15]; return *this; } I did have a nested loop to do this but I ended up writing it all out while trying to find out an answer to this problem. Bear in mind the matrices are in column major and do not get transposed by OpenGL The rotation and translation matrices are as follows but I don't believe there is any problem with them: Matrix4 Matrix4::translation(const Vector3 &translation) { Matrix4 result(1.0f); result.elements[0 + 3 * 4] = translation.x; result.elements[1 + 3 * 4] = translation.y; result.elements[2 + 3 * 4] = translation.z; return result; } Matrix4 Matrix4::rotation(float angle, const Vector3 &axis) { Matrix4 result(1.0f); float r = toRadians(angle); float c = (float)cos(r); float s = (float)sin(r); float cFlip = 1.0f - c; result.elements[0 + 0 * 4] = axis.x * cFlip + c; result.elements[1 + 0 * 4] = axis.y * axis.x * cFlip + axis.z * s; result.elements[2 + 0 * 4] = axis.x * axis.z * cFlip - axis.y * s; result.elements[0 + 1 * 4] = axis.x * axis.y * cFlip - axis.z * s; result.elements[1 + 1 * 4] = axis.y * cFlip + c; result.elements[2 + 1 * 4] = axis.y * axis.z * cFlip + axis.x * s; result.elements[0 + 2 * 4] = axis.x * axis.y * cFlip + axis.y * s; result.elements[1 + 2 * 4] = axis.y * axis.z * cFlip - axis.x * s; result.elements[2 + 2 * 4] = axis.z * cFlip + c; return result; } Any ideas on what the problem here could be or how to fix it would be greatly appreciated :^)
At your multiply function, you wrote: elements[0] = elements[0] * other.elements[0] ... ... Notice that element[0] got its contents actualized now and then you do: elements[8] = elements[0] * other.elements[8] ... which use the new value and not the original one. I guess, you want to make a copy of your original matrix before doing this multiplication
opssss !! i just saw !!! in your multiply, your output matrice is the first input matrix, so the latest operations are calculated with coefficient of the multiplied matrix !! : elements[0] = elements[0] * ..... .... elements[4] = elements[0] * ..... /* here element[ 0 ] is the top left element of the multiplied matix */ moreover, operator* shouldn't modfify (nor return) one of his operand, operator*= is here for that
Need documentation that describes the output of OpenGL's rotate method
I have created a custom cube whose sides can be removed. I would eventually like to print the cube to a paper printer. I would like to do my own rotation by using the output from the OpenGL rotate method. My question: Does documentation exist that describes the Identity Matrix after a rotation? Or is the source available for the OpenGL rotate method?
glRotate creates a rotation matrix and multiplies that in place on the matrix on top of the current matrix stack. Rotation matrices are a well known thing in linear algebra.
You can read about Matrix calculations and Matrix Transformations all over the internet, here is a few links. Matrix Mathematics Transformation Matrix OpenGL Programming/3D/Matrices Though here is something I've created for calculating exactly what you're trying to calculate. There isn't much so explain because it is basically just a bunch of math formulas. public class Matrix4 { public float m00, m01, m02, m03; public float m10, m11, m12, m13; public float m20, m21, m22, m23; public float m30, m31, m32, m33; public Matrix4() { this.set( 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f); } public void rotate(float angle, float x, float y, float z) { float sin = (float) Math.sin(angle); float cos = (float) Math.cos(angle); if ((x * x + y * y + z * z) != 1f) { float length = (float) Math.sqrt(x * x + y * y + z * z); if (length > 0f) { length = 1f / length; x *= length; y *= length; z *= length; } } this.mul( x * x * (1f - cos) + cos, x * y * (1f - cos) - z * sin, x * z * (1f - cos) + y * sin, 0f, y * x * (1f - cos) + z * sin, y * y * (1f - cos) + cos, y * z * (1f - cos) - x * sin, 0f, x * z * (1f - cos) - y * sin, y * z * (1f - cos) + x * sin, z * z * (1f - cos) + cos, 0f, 0f, 0f, 0f, 1f); } public void mul( float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33) { float mm00 = this.m00 * m00 + this.m01 * m10 + this.m02 * m20 + this.m03 * m30; float mm01 = this.m00 * m01 + this.m01 * m11 + this.m02 * m21 + this.m03 * m31; float mm02 = this.m00 * m02 + this.m01 * m12 + this.m02 * m22 + this.m03 * m32; float mm03 = this.m00 * m03 + this.m01 * m13 + this.m02 * m23 + this.m03 * m33; float mm10 = this.m10 * m00 + this.m11 * m10 + this.m12 * m20 + this.m13 * m30; float mm11 = this.m10 * m01 + this.m11 * m11 + this.m12 * m21 + this.m13 * m31; float mm12 = this.m10 * m02 + this.m11 * m12 + this.m12 * m22 + this.m13 * m32; float mm13 = this.m10 * m03 + this.m11 * m13 + this.m12 * m23 + this.m13 * m33; float mm20 = this.m20 * m00 + this.m21 * m10 + this.m22 * m20 + this.m23 * m30; float mm21 = this.m20 * m01 + this.m21 * m11 + this.m22 * m21 + this.m23 * m31; float mm22 = this.m20 * m02 + this.m21 * m12 + this.m22 * m22 + this.m23 * m32; float mm23 = this.m20 * m03 + this.m21 * m13 + this.m22 * m23 + this.m23 * m33; float mm30 = this.m30 * m00 + this.m31 * m10 + this.m32 * m20 + this.m33 * m30; float mm31 = this.m30 * m01 + this.m31 * m11 + this.m32 * m21 + this.m33 * m31; float mm32 = this.m30 * m02 + this.m31 * m12 + this.m32 * m22 + this.m33 * m32; float mm33 = this.m30 * m03 + this.m31 * m13 + this.m32 * m23 + this.m33 * m33; this.m00 = mm00; this.m01 = mm01; this.m02 = mm02; this.m03 = mm03; this.m10 = mm10; this.m11 = mm11; this.m12 = mm12; this.m13 = mm13; this.m20 = mm20; this.m21 = mm21; this.m22 = mm22; this.m23 = mm23; this.m30 = mm30; this.m31 = mm31; this.m32 = mm32; this.m33 = mm33; } public void set( float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33) { this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; } } The following will create an Identity Matrix Matrix4 m = new Matrix4(); Important do notice that the angle given in the rotate() function in Matrix4 is in radians where in OpenGL the glRotate() functions requires the angle to be in degrees. Also if the Matrix is "opposite", when you are using it then simply before you use the Matrix for anything else calculate the Transpose of the matrix, and then you can use it.
How Calculate NORMAL in triangle strip
i have a problem with the lighting of my OPENGL projects. I program on c++ using ECLIPSE. I have a terrein construited by triangle strip. the code of my render is the follow: HeightMap::~HeightMap(void) { } float HeightMap::getScaledGrayColor(double height) { float fColor = NULL; if (height == this->NODATA_value) { return 0.0f; } fColor = ((255.00f / max) * height) / 255.00f; return fColor; } double* HeightMap::getHeights(int rowNumber) { rowNumber = rowNumber + 6; ifstream fin(this->filename); string s; long length; fin.seekg(0, ios::beg); // go to the first line for (int i = 0; i < rowNumber; i++) { // loop 'till the desired line getline(fin, s); } string nextToken; getline(fin, nextToken); StringUtils stringUtils; vector<string> tempVec = stringUtils.split(nextToken, " "); double* heights = new double[this->ncols]; for (int i = 0; i < tempVec.size() - 1; i++) { heights[i] = strtod(tempVec[i].c_str(), NULL); } return heights; } void HeightMap::Render(void) { int x = 0; int i = 0; for (int i = 0, j = 0; j < nrows; i--, j++) { //cout<<"valore di i è: "<<i<<endl; //cout<<"valore di j è: "<<j<<endl; double * rowHeights = this->getHeights(j);// for (int x = 0; x < ncols; x++) { float color = getScaledGrayColor(rowHeights[x]); double * Quote = this->getHeights(x); glBegin(GL_TRIANGLE_STRIP); glColor3f(color, color, color); //triangolo ABC //glNormal3f((x * cellsize), (i * cellsize), 0); glVertex3f((x * cellsize), (i * cellsize), 0); //vertice base //glNormal3f((x * cellsize), ((i * cellsize) + cellsize), 0); glVertex3f((x * cellsize), ((i * cellsize) + cellsize), 0);//vertice base //glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize) + (cellsize / 2)), *Quote);//vertice altezza //triangolo DEF //glNormal3f((x * cellsize), (i * cellsize) + cellsize, 0); glVertex3f((x * cellsize), (i * cellsize) + cellsize, 0); //vertice base //glNormal3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0);//vertice base glVertex3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0);//vertice base //glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize) + (cellsize / 2)), *Quote);//vertice altezza //triangolo GHI //glNormal3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0); //vertice base glVertex3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0); //vertice base //glNormal3f((x * cellsize) + cellsize, i * cellsize, 0);//vertice base glVertex3f((x * cellsize) + cellsize, i * cellsize, 0);//vertice base //glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize) + (cellsize / 2)), *Quote);//vertice altezza //triangolo LMN //glNormal3f((x * cellsize), (i * cellsize), 0); //vertice base glVertex3f((x * cellsize), (i * cellsize), 0); //vertice base //glNormal3f((x * cellsize) + cellsize, (i * cellsize), 0);//vertice base glVertex3f((x * cellsize) + cellsize, (i * cellsize), 0);//vertice base //glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize) + (cellsize / 2)), *Quote);//vertice altezza glEnd(); } //} } } i try to use a normal for vertex but i don't know how calculate the argument of glnormal function. Then i must use a normal for face. Can you help me with this problem? yes, i need normal by face and after i must do normal by vertex: for normal by face i do this void HeightMap::Render(void) { int x = 0; int i = 0; glPushMatrix(); glRotatef(angle, xrot, yrot, zrot);//rotate the object cout<<"valore di nrows è: "<getHeights(j); float vectorba[3]={0.0,0.0,0.0}; float vectorcb[3]={0.0,0.0,0.0}; float xnormal = 0.0; float ynormal = 0.0; float znormal = 0.0; float len=0.0; for (int x = 0; x < ncols; x++) { //if (rowHeights[x] != this->NODATA_value) { float color = getScaledGrayColor(rowHeights[x]); double * Quote = this->getHeights(x); glBegin(GL_TRIANGLE_STRIP); glColor3f(color, color, color); //triangolo ABC //inizio normal vectorba[0]={(x * cellsize)-(x * cellsize)}; vectorba[1]={((i * cellsize) + cellsize)-(i * cellsize)}; vectorcb[0]={((x * cellsize) + (cellsize / 2))-(x * cellsize)}; vectorcb[1]={((i * cellsize) + (cellsize / 2))-((i * cellsize) +cellsize)}; vectorcb[2]=*Quote; // calculate the cross product and place the resulting vector // into the variable xnormal,ynormal e znormal xnormal = (vectorba[1] * vectorcb[2]) - (vectorba[2] * vectorcb[1]); ynormal = (vectorba[2] * vectorcb[0]) - (vectorba[0] * vectorcb[2]); znormal = (vectorba[0] * vectorcb[1]) - (vectorba[1] * vectorcb[0]); //fine normal //inizio normalize // calculate the length of the vector len = (float)(sqrt((xnormal * xnormal) + (ynormal * ynormal) + (znormal * znormal))); // avoid division by 0 if (len == 0.0f) len = 1.0f; // reduce to unit size xnormal /= len; ynormal /= len; znormal /= len; //fine normalize //glNormal3f((x * cellsize), (i * cellsize), 0); //normal per vertex. controllare la formula glVertex3f((x * cellsize), (i * cellsize), 0); //vertice base A //glNormal3f((x * cellsize), ((i * cellsize) + cellsize), 0); glVertex3f((x * cellsize), ((i * cellsize) + cellsize), 0);//vertice base B glNormal3f(xnormal, ynormal, znormal); //normal per face //glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize) + (cellsize / 2)), *Quote);//vertice altezza C //triangolo DEF //inizio normal vectorba[0]={(x * cellsize) + cellsize-(x * cellsize)}; vectorba[1]={((i * cellsize) + cellsize)-((i * cellsize) + cellsize)}; vectorcb[0]={((x * cellsize) + (cellsize / 2))-(x * cellsize) + cellsize}; vectorcb[1]={((i * cellsize)+ (cellsize / 2))-((i * cellsize) + cellsize)}; vectorcb[2]=*Quote; // calculate the cross product and place the resulting vector // into the variable xnormal,ynormal e znormal xnormal = (vectorba[1] * vectorcb[2]) - (vectorba[2] * vectorcb[1]); ynormal = (vectorba[2] * vectorcb[0]) - (vectorba[0] * vectorcb[2]); znormal = (vectorba[0] * vectorcb[1]) - (vectorba[1] * vectorcb[0]); //fine normal //inizio normalize // calculate the length of the vector len = (float)(sqrt((xnormal * xnormal) + (ynormal * ynormal) + (znormal * znormal))); // avoid division by 0 if (len == 0.0f) len = 1.0f; // reduce to unit size xnormal /= len; ynormal /= len; znormal /= len; //fine normalize //glNormal3f((x * cellsize), (i * cellsize) + cellsize, 0); glVertex3f((x * cellsize), (i * cellsize) + cellsize, 0); //vertice base D //glNormal3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0);//vertice base glVertex3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0);//vertice base E glNormal3f(xnormal, ynormal, znormal); //normal per face //glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza F //triangolo GHI //inizio normal vectorba[0]={(x * cellsize) + cellsize-(x * cellsize) + cellsize}; vectorba[1]={i * cellsize-(i * cellsize) + cellsize}; vectorcb[0]={((x * cellsize) + (cellsize / 2))-(x * cellsize) + cellsize}; vectorcb[1]={((i * cellsize)+ (cellsize / 2))-(i * cellsize)}; vectorcb[2]=*Quote; // calculate the cross product and place the resulting vector // into the variable xnormal,ynormal e znormal xnormal = (vectorba[1] * vectorcb[2]) - (vectorba[2] * vectorcb[1]); ynormal = (vectorba[2] * vectorcb[0]) - (vectorba[0] * vectorcb[2]); znormal = (vectorba[0] * vectorcb[1]) - (vectorba[1] * vectorcb[0]); //fine normal //inizio normalize // calculate the length of the vector len = (float)(sqrt((xnormal * xnormal) + (ynormal * ynormal) + (znormal * znormal))); // avoid division by 0 if (len == 0.0f) len = 1.0f; // reduce to unit size xnormal /= len; ynormal /= len; znormal /= len; //fine normalize //glNormal3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0); //vertice base glVertex3f((x * cellsize) + cellsize, (i * cellsize) + cellsize, 0); //vertice base G //glNormal3f((x * cellsize) + cellsize, i * cellsize, 0);//vertice base glVertex3f((x * cellsize) + cellsize, i * cellsize, 0);//vertice base H glNormal3f(xnormal, ynormal, znormal); //normal per face //glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza I //triangolo LMN //inizio normal vectorba[0]={(x * cellsize) + cellsize-(x * cellsize)}; vectorba[1]={(i * cellsize)-(i * cellsize)}; vectorcb[0]={((x * cellsize) + (cellsize / 2))-(x * cellsize) + cellsize}; vectorcb[1]={((i * cellsize)+ (cellsize / 2))-(i * cellsize)}; vectorcb[2]=*Quote; // calculate the cross product and place the resulting vector // into the variable xnormal,ynormal e znormal xnormal = (vectorba[1] * vectorcb[2]) - (vectorba[2] * vectorcb[1]); ynormal = (vectorba[2] * vectorcb[0]) - (vectorba[0] * vectorcb[2]); znormal = (vectorba[0] * vectorcb[1]) - (vectorba[1] * vectorcb[0]); //fine normal //inizio normalize // calculate the length of the vector len = (float)(sqrt((xnormal * xnormal) + (ynormal * ynormal) + (znormal * znormal))); // avoid division by 0 if (len == 0.0f) len = 1.0f; // reduce to unit size xnormal /= len; ynormal /= len; znormal /= len; //fine normalize //glNormal3f((x * cellsize), (i * cellsize), 0); //vertice base glVertex3f((x * cellsize), (i * cellsize), 0); //vertice base L //glNormal3f((x * cellsize) + cellsize, (i * cellsize), 0);//vertice base glVertex3f((x * cellsize) + cellsize, (i * cellsize), 0);//vertice base M glNormal3f(xnormal, ynormal, znormal); //normal per face //glNormal3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza glVertex3f(((x * cellsize) + (cellsize / 2)), ((i * cellsize)+ (cellsize / 2)), *Quote);//vertice altezza N glEnd(); } //} } glPopMatrix(); } the formulation is right? how can i transform the Render using the function for normal and normalize?
If I understood, you want the normal by face? If you have the triangle points you can calculate the normal for each face. Take a look at this: http://www.opengl.org/wiki/Calculating_a_Surface_Normal The normal by vertex could be calculated taking the avg normals between faces.